killbill-aplcache
Changes
beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithInvoicePlugin.java 19(+19 -0)
invoice/src/main/java/org/killbill/billing/invoice/provider/DefaultNoOpInvoiceProviderPlugin.java 27(+23 -4)
pom.xml 2(+1 -1)
Details
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithInvoicePlugin.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithInvoicePlugin.java
index c8780b4..17a7e68 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithInvoicePlugin.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithInvoicePlugin.java
@@ -45,8 +45,12 @@ import org.killbill.billing.invoice.model.ExternalChargeInvoiceItem;
import org.killbill.billing.invoice.model.ItemAdjInvoiceItem;
import org.killbill.billing.invoice.model.TaxInvoiceItem;
import org.killbill.billing.invoice.notification.DefaultNextBillingDateNotifier;
+import org.killbill.billing.invoice.plugin.api.InvoiceContext;
import org.killbill.billing.invoice.plugin.api.InvoicePluginApi;
import org.killbill.billing.invoice.plugin.api.InvoicePluginApiRetryException;
+import org.killbill.billing.invoice.plugin.api.OnFailureInvoiceResult;
+import org.killbill.billing.invoice.plugin.api.OnSuccessInvoiceResult;
+import org.killbill.billing.invoice.plugin.api.PriorInvoiceResult;
import org.killbill.billing.osgi.api.OSGIServiceDescriptor;
import org.killbill.billing.osgi.api.OSGIServiceRegistration;
import org.killbill.billing.payment.api.PluginProperty;
@@ -402,6 +406,11 @@ public class TestWithInvoicePlugin extends TestIntegrationBase {
InvoiceItem additionalInvoiceItem;
@Override
+ public PriorInvoiceResult priorCall(final InvoiceContext invoiceContext, final Iterable<PluginProperty> iterable) {
+ return null;
+ }
+
+ @Override
public List<InvoiceItem> getAdditionalInvoiceItems(final Invoice invoice, final boolean isDryRun, final Iterable<PluginProperty> pluginProperties, final CallContext callContext) {
if (shouldThrowException) {
throw new InvoicePluginApiRetryException();
@@ -412,6 +421,16 @@ public class TestWithInvoicePlugin extends TestIntegrationBase {
}
}
+ @Override
+ public OnSuccessInvoiceResult onSuccessCall(final InvoiceContext invoiceContext, final Iterable<PluginProperty> iterable) {
+ return null;
+ }
+
+ @Override
+ public OnFailureInvoiceResult onFailureCall(final InvoiceContext invoiceContext, final Iterable<PluginProperty> iterable) {
+ return null;
+ }
+
private InvoiceItem createTaxInvoiceItem(final Invoice invoice) {
return new TaxInvoiceItem(invoice.getId(), invoice.getAccountId(), null, "Tax Item", clock.getUTCNow().toLocalDate(), BigDecimal.ONE, invoice.getCurrency());
}
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithTaxItems.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithTaxItems.java
index c02877a..d0cfcee 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithTaxItems.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithTaxItems.java
@@ -40,7 +40,11 @@ import org.killbill.billing.invoice.api.InvoiceItem;
import org.killbill.billing.invoice.api.InvoiceItemType;
import org.killbill.billing.invoice.model.ExternalChargeInvoiceItem;
import org.killbill.billing.invoice.model.TaxInvoiceItem;
+import org.killbill.billing.invoice.plugin.api.InvoiceContext;
import org.killbill.billing.invoice.plugin.api.InvoicePluginApi;
+import org.killbill.billing.invoice.plugin.api.OnFailureInvoiceResult;
+import org.killbill.billing.invoice.plugin.api.OnSuccessInvoiceResult;
+import org.killbill.billing.invoice.plugin.api.PriorInvoiceResult;
import org.killbill.billing.osgi.api.OSGIServiceDescriptor;
import org.killbill.billing.osgi.api.OSGIServiceRegistration;
import org.killbill.billing.payment.api.PluginProperty;
@@ -293,15 +297,30 @@ public class TestWithTaxItems extends TestIntegrationBase {
}
@Override
+ public PriorInvoiceResult priorCall(final InvoiceContext invoiceContext, final Iterable<PluginProperty> iterable) {
+ return null;
+ }
+
+ @Override
public List<InvoiceItem> getAdditionalInvoiceItems(final Invoice invoice, final boolean isDryRun, final Iterable<PluginProperty> pluginProperties, final CallContext callContext) {
final List<InvoiceItem> result = new ArrayList<InvoiceItem>();
- for (TaxInvoiceItem item : taxItems) {
+ for (final TaxInvoiceItem item : taxItems) {
result.add(new TaxInvoiceItem(item.getId(), invoice.getId(), invoice.getAccountId(), item.getBundleId(), "Tax Item", item.getStartDate(), item.getAmount(), invoice.getCurrency()));
}
taxItems.clear();
return result;
}
+ @Override
+ public OnSuccessInvoiceResult onSuccessCall(final InvoiceContext invoiceContext, final Iterable<PluginProperty> iterable) {
+ return null;
+ }
+
+ @Override
+ public OnFailureInvoiceResult onFailureCall(final InvoiceContext invoiceContext, final Iterable<PluginProperty> iterable) {
+ return null;
+ }
+
public void reset() {
taxItems.clear();
}
@@ -309,6 +328,5 @@ public class TestWithTaxItems extends TestIntegrationBase {
public void addTaxItem(final TaxInvoiceItem item) {
taxItems.add(item);
}
-
}
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/api/DefaultInvoiceContext.java b/invoice/src/main/java/org/killbill/billing/invoice/api/DefaultInvoiceContext.java
new file mode 100644
index 0000000..8f7f37b
--- /dev/null
+++ b/invoice/src/main/java/org/killbill/billing/invoice/api/DefaultInvoiceContext.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.invoice.api;
+
+import java.util.List;
+
+import org.joda.time.LocalDate;
+import org.killbill.billing.callcontext.DefaultCallContext;
+import org.killbill.billing.invoice.plugin.api.InvoiceContext;
+import org.killbill.billing.util.callcontext.CallContext;
+
+public class DefaultInvoiceContext extends DefaultCallContext implements InvoiceContext {
+
+ private final LocalDate targetDate;
+ private final Invoice invoice;
+ private final List<Invoice> existingInvoices;
+ private final boolean isDryRun;
+ private final boolean isRescheduled;
+
+ public DefaultInvoiceContext(final LocalDate targetDate,
+ final Invoice invoice,
+ final List<Invoice> existingInvoices,
+ final boolean isDryRun,
+ final boolean isRescheduled,
+ final CallContext context) {
+ super(context.getAccountId(),
+ context.getTenantId(),
+ context.getUserName(),
+ context.getCallOrigin(),
+ context.getUserType(),
+ context.getReasonCode(),
+ context.getComments(),
+ context.getUserToken(),
+ context.getCreatedDate(),
+ context.getUpdatedDate());
+ this.targetDate = targetDate;
+ this.invoice = invoice;
+ this.existingInvoices = existingInvoices;
+ this.isDryRun = isDryRun;
+ this.isRescheduled = isRescheduled;
+ }
+
+ @Override
+ public LocalDate getTargetDate() {
+ return targetDate;
+ }
+
+ @Override
+ public Invoice getInvoice() {
+ return invoice;
+ }
+
+ @Override
+ public List<Invoice> getExistingInvoices() {
+ return existingInvoices;
+ }
+
+ @Override
+ public boolean isDryRun() {
+ return isDryRun;
+ }
+
+ @Override
+ public boolean isRescheduled() {
+ return isRescheduled;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("DefaultInvoiceContext{");
+ sb.append("targetDate=").append(targetDate);
+ sb.append(", invoice=").append(invoice);
+ sb.append(", isDryRun=").append(isDryRun);
+ sb.append(", isRescheduled=").append(isRescheduled);
+ sb.append(", accountId=").append(accountId);
+ sb.append(", tenantId=").append(tenantId);
+ sb.append(", userToken=").append(userToken);
+ sb.append(", userName='").append(userName).append('\'');
+ sb.append(", callOrigin=").append(callOrigin);
+ sb.append(", userType=").append(userType);
+ sb.append(", reasonCode='").append(reasonCode).append('\'');
+ sb.append(", comments='").append(comments).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+
+ final DefaultInvoiceContext that = (DefaultInvoiceContext) o;
+
+ if (isDryRun != that.isDryRun) {
+ return false;
+ }
+ if (isRescheduled != that.isRescheduled) {
+ return false;
+ }
+ if (targetDate != null ? targetDate.compareTo(that.targetDate) != 0 : that.targetDate != null) {
+ return false;
+ }
+ if (invoice != null ? !invoice.equals(that.invoice) : that.invoice != null) {
+ return false;
+ }
+ return existingInvoices != null ? existingInvoices.equals(that.existingInvoices) : that.existingInvoices == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (targetDate != null ? targetDate.hashCode() : 0);
+ result = 31 * result + (invoice != null ? invoice.hashCode() : 0);
+ result = 31 * result + (existingInvoices != null ? existingInvoices.hashCode() : 0);
+ result = 31 * result + (isDryRun ? 1 : 0);
+ result = 31 * result + (isRescheduled ? 1 : 0);
+ return result;
+ }
+}
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 c4e791f..16835c6 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
@@ -31,11 +31,13 @@ import javax.inject.Inject;
import org.joda.time.LocalDate;
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.invoice.InvoicePluginDispatcher;
import org.killbill.billing.invoice.dao.InvoiceDao;
import org.killbill.billing.invoice.dao.InvoiceItemModelDao;
import org.killbill.billing.invoice.dao.InvoiceModelDao;
+import org.killbill.billing.invoice.model.DefaultInvoice;
import org.killbill.billing.invoice.model.InvoiceItemFactory;
import org.killbill.billing.invoice.model.ItemAdjInvoiceItem;
import org.killbill.billing.util.UUIDs;
@@ -76,11 +78,21 @@ public class InvoiceApiHelper {
}
public List<InvoiceItem> dispatchToInvoicePluginsAndInsertItems(final UUID accountId, final boolean isDryRun, final WithAccountLock withAccountLock, final CallContext context) throws InvoiceApiException {
+ // Invoked by User API call
+ final LocalDate targetDate = null;
+ final List<Invoice> existingInvoices = null;
+ final boolean isRescheduled = false;
+
+ final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(accountId, context);
+ invoicePluginDispatcher.priorCall(targetDate, existingInvoices, isDryRun, isRescheduled, context, internalTenantContext);
+
+ boolean success = false;
GlobalLock lock = null;
+ Iterable<Invoice> invoicesForPlugins = null;
try {
lock = locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), accountId.toString(), invoiceConfig.getMaxGlobalLockRetries());
- final Iterable<Invoice> invoicesForPlugins = withAccountLock.prepareInvoices();
+ invoicesForPlugins = withAccountLock.prepareInvoices();
final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(accountId, context);
final List<InvoiceModelDao> invoiceModelDaos = new LinkedList<InvoiceModelDao>();
@@ -100,6 +112,8 @@ public class InvoiceApiHelper {
}
final List<InvoiceItemModelDao> createdInvoiceItems = dao.createInvoices(invoiceModelDaos, internalCallContext);
+ success = true;
+
return fromInvoiceItemModelDao(createdInvoiceItems);
} catch (final LockFailedException e) {
log.warn("Failed to process invoice items for accountId='{}'", accountId.toString(), e);
@@ -108,6 +122,15 @@ public class InvoiceApiHelper {
if (lock != null) {
lock.release();
}
+
+ if (success) {
+ for (final Invoice invoiceForPlugin : invoicesForPlugins) {
+ final DefaultInvoice refreshedInvoice = new DefaultInvoice(dao.getById(invoiceForPlugin.getId(), internalTenantContext));
+ invoicePluginDispatcher.onSuccessCall(targetDate, refreshedInvoice, existingInvoices, isDryRun, isRescheduled, context, internalTenantContext);
+ }
+ } else {
+ invoicePluginDispatcher.onFailureCall(targetDate, null, existingInvoices, isDryRun, isRescheduled, context, internalTenantContext);
+ }
}
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java b/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
index fa42a24..b936c5a 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
@@ -509,11 +509,17 @@ public class InvoiceDispatcher {
final List<Invoice> existingInvoices,
final boolean isDryRun,
final InternalCallContext internalCallContext) throws InvoiceApiException {
+ final boolean isRescheduled = false; // TODO
+
+ final CallContext callContext = buildCallContext(internalCallContext);
+ invoicePluginDispatcher.priorCall(targetDate, existingInvoices, isDryRun, isRescheduled, callContext, internalCallContext);
+
final ImmutableAccountData account;
try {
account = accountApi.getImmutableAccountDataById(accountId, internalCallContext);
} catch (final AccountApiException e) {
log.error("Unable to generate invoice for accountId='{}', a future notification has NOT been recorded", accountId, e);
+ invoicePluginDispatcher.onFailureCall(targetDate, null, existingInvoices, isDryRun, isRescheduled, callContext, internalCallContext);
return null;
}
@@ -525,6 +531,8 @@ public class InvoiceDispatcher {
// If invoice comes back null, there is nothing new to generate, we can bail early
if (invoice == null) {
+ invoicePluginDispatcher.onSuccessCall(targetDate, null, existingInvoices, isDryRun, isRescheduled, callContext, internalCallContext);
+
if (isDryRun) {
log.info("Generated null dryRun invoice for accountId='{}', targetDate='{}'", accountId, targetDate);
} else {
@@ -551,7 +559,6 @@ public class InvoiceDispatcher {
//
// Ask external invoice plugins if additional items (tax, etc) shall be added to the invoice
//
- final CallContext callContext = buildCallContext(internalCallContext);
final List<InvoiceItem> additionalInvoiceItemsFromPlugins = invoicePluginDispatcher.getAdditionalInvoiceItems(tmpInvoiceForInvoicePlugins, isDryRun, callContext, internalCallContext);
if (additionalInvoiceItemsFromPlugins.isEmpty()) {
// PERF: avoid re-computing the CBA if no change was made
@@ -559,7 +566,6 @@ public class InvoiceDispatcher {
invoice.addInvoiceItem(cbaItemPreInvoicePlugins);
}
} else {
-
// Add or update items from generated invoice
for (final InvoiceItem cur : additionalInvoiceItemsFromPlugins) {
final InvoiceItem exitingItem = Iterables.tryFind(tmpInvoiceForInvoicePlugins.getInvoiceItems(), new Predicate<InvoiceItem>() {
@@ -605,7 +611,6 @@ public class InvoiceDispatcher {
}
if (!isDryRun) {
-
// Compute whether this is a new invoice object (or just some adjustments on an existing invoice), and extract invoiceIds for later use
final Set<UUID> uniqueInvoiceIds = getUniqueInvoiceIds(invoice);
final boolean isRealInvoiceWithItems = uniqueInvoiceIds.remove(invoice.getId());
@@ -634,6 +639,13 @@ public class InvoiceDispatcher {
if (!isDryRun && !success) {
commitInvoiceAndSetFutureNotifications(account, null, futureAccountNotifications, internalCallContext);
}
+
+ if (success) {
+ final DefaultInvoice refreshedInvoice = new DefaultInvoice(invoiceDao.getById(invoice.getId(), internalCallContext));
+ invoicePluginDispatcher.onSuccessCall(targetDate, refreshedInvoice, existingInvoices, isDryRun, isRescheduled, callContext, internalCallContext);
+ } else {
+ invoicePluginDispatcher.onFailureCall(targetDate, invoice, existingInvoices, isDryRun, isRescheduled, callContext, internalCallContext);
+ }
}
return invoice;
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/InvoicePluginDispatcher.java b/invoice/src/main/java/org/killbill/billing/invoice/InvoicePluginDispatcher.java
index 45b12f8..2c3a6b1 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/InvoicePluginDispatcher.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/InvoicePluginDispatcher.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2014-2015 Groupon, Inc
- * Copyright 2014-2015 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -25,13 +25,16 @@ import java.util.Set;
import javax.inject.Inject;
+import org.joda.time.LocalDate;
import org.killbill.billing.ErrorCode;
import org.killbill.billing.callcontext.InternalTenantContext;
+import org.killbill.billing.invoice.api.DefaultInvoiceContext;
import org.killbill.billing.invoice.api.Invoice;
import org.killbill.billing.invoice.api.InvoiceApiException;
import org.killbill.billing.invoice.api.InvoiceItem;
import org.killbill.billing.invoice.api.InvoiceItemType;
import org.killbill.billing.invoice.model.DefaultInvoice;
+import org.killbill.billing.invoice.plugin.api.InvoiceContext;
import org.killbill.billing.invoice.plugin.api.InvoicePluginApi;
import org.killbill.billing.osgi.api.OSGIServiceRegistration;
import org.killbill.billing.payment.api.PluginProperty;
@@ -48,14 +51,13 @@ public class InvoicePluginDispatcher {
private static final Logger log = LoggerFactory.getLogger(InvoicePluginDispatcher.class);
public static final Collection<InvoiceItemType> ALLOWED_INVOICE_ITEM_TYPES = ImmutableList.<InvoiceItemType>of(InvoiceItemType.EXTERNAL_CHARGE,
- InvoiceItemType.ITEM_ADJ,
- InvoiceItemType.CREDIT_ADJ,
- InvoiceItemType.TAX);
+ InvoiceItemType.ITEM_ADJ,
+ InvoiceItemType.CREDIT_ADJ,
+ InvoiceItemType.TAX);
private final OSGIServiceRegistration<InvoicePluginApi> pluginRegistry;
private final InvoiceConfig invoiceConfig;
-
@Inject
public InvoicePluginDispatcher(final OSGIServiceRegistration<InvoicePluginApi> pluginRegistry,
final InvoiceConfig invoiceConfig) {
@@ -63,15 +65,78 @@ public class InvoicePluginDispatcher {
this.invoiceConfig = invoiceConfig;
}
+ public void priorCall(final LocalDate targetDate, final List<Invoice> existingInvoices, final boolean isDryRun, final boolean isRescheduled, final CallContext callContext, final InternalTenantContext internalTenantContext) {
+ final List<InvoicePluginApi> invoicePlugins = getInvoicePlugins(internalTenantContext);
+ if (invoicePlugins.isEmpty()) {
+ return;
+ }
+
+ final InvoiceContext invoiceContext = new DefaultInvoiceContext(targetDate, null, existingInvoices, isDryRun, isRescheduled, callContext);
+ for (final InvoicePluginApi invoicePlugin : invoicePlugins) {
+ invoicePlugin.priorCall(invoiceContext, ImmutableList.<PluginProperty>of());
+ }
+ }
+
+ public void onSuccessCall(final LocalDate targetDate,
+ final DefaultInvoice invoice,
+ final List<Invoice> existingInvoices,
+ final boolean isDryRun,
+ final boolean isRescheduled,
+ final CallContext callContext,
+ final InternalTenantContext internalTenantContext) {
+ onCompletionCall(true, targetDate, invoice, existingInvoices, isDryRun, isRescheduled, callContext, internalTenantContext);
+ }
+
+ public void onFailureCall(final LocalDate targetDate,
+ final DefaultInvoice invoice,
+ final List<Invoice> existingInvoices,
+ final boolean isDryRun,
+ final boolean isRescheduled,
+ final CallContext callContext,
+ final InternalTenantContext internalTenantContext) {
+ onCompletionCall(false, targetDate, invoice, existingInvoices, isDryRun, isRescheduled, callContext, internalTenantContext);
+ }
+
+ private void onCompletionCall(final boolean isSuccess,
+ final LocalDate targetDate,
+ final DefaultInvoice originalInvoice,
+ final List<Invoice> existingInvoices,
+ final boolean isDryRun,
+ final boolean isRescheduled,
+ final CallContext callContext,
+ final InternalTenantContext internalTenantContext) {
+ final List<InvoicePluginApi> invoicePlugins = getInvoicePlugins(internalTenantContext);
+ if (invoicePlugins.isEmpty()) {
+ return;
+ }
+
+ // We clone the original invoice so plugins don't remove/add items
+ final Invoice clonedInvoice = (Invoice) originalInvoice.clone();
+ final InvoiceContext invoiceContext = new DefaultInvoiceContext(targetDate, clonedInvoice, existingInvoices, isDryRun, isRescheduled, callContext);
+
+ for (final InvoicePluginApi invoicePlugin : invoicePlugins) {
+ if (isSuccess) {
+ invoicePlugin.onSuccessCall(invoiceContext, ImmutableList.<PluginProperty>of());
+ } else {
+ invoicePlugin.onFailureCall(invoiceContext, ImmutableList.<PluginProperty>of());
+ }
+ }
+ }
+
//
// If we have multiple plugins there is a question of plugin ordering and also a 'product' questions to decide whether
// subsequent plugins should have access to items added by previous plugins
//
public List<InvoiceItem> getAdditionalInvoiceItems(final Invoice originalInvoice, final boolean isDryRun, final CallContext callContext, final InternalTenantContext tenantContext) throws InvoiceApiException {
- // We clone the original invoice so plugins don't remove/add items
- final Invoice clonedInvoice = (Invoice) ((DefaultInvoice) originalInvoice).clone();
final List<InvoiceItem> additionalInvoiceItems = new LinkedList<InvoiceItem>();
+
final List<InvoicePluginApi> invoicePlugins = getInvoicePlugins(tenantContext);
+ if (invoicePlugins.isEmpty()) {
+ return additionalInvoiceItems;
+ }
+
+ // We clone the original invoice so plugins don't remove/add items
+ final Invoice clonedInvoice = (Invoice) ((DefaultInvoice) originalInvoice).clone();
for (final InvoicePluginApi invoicePlugin : invoicePlugins) {
final List<InvoiceItem> items = invoicePlugin.getAdditionalInvoiceItems(clonedInvoice, isDryRun, ImmutableList.<PluginProperty>of(), callContext);
if (items != null) {
@@ -93,7 +158,6 @@ public class InvoicePluginDispatcher {
private List<InvoicePluginApi> getInvoicePlugins(final InternalTenantContext tenantContext) {
-
final Collection<String> resultingPluginList = getResultingPluginNameList(tenantContext);
final List<InvoicePluginApi> invoicePlugins = new ArrayList<InvoicePluginApi>();
@@ -112,7 +176,7 @@ public class InvoicePluginDispatcher {
if (configuredPlugins == null || configuredPlugins.isEmpty()) {
return registeredPlugins;
} else {
- final List<String> result = new ArrayList<String>(configuredPlugins.size());
+ final List<String> result = new ArrayList<String>(configuredPlugins.size());
for (final String name : configuredPlugins) {
if (pluginRegistry.getServiceForName(name) != null) {
result.add(name);
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/provider/DefaultNoOpInvoiceProviderPlugin.java b/invoice/src/main/java/org/killbill/billing/invoice/provider/DefaultNoOpInvoiceProviderPlugin.java
index 503d5e9..30e4371 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/provider/DefaultNoOpInvoiceProviderPlugin.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/provider/DefaultNoOpInvoiceProviderPlugin.java
@@ -1,7 +1,8 @@
/*
- * Copyright 2014 Groupon, Inc
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Groupon licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -20,10 +21,13 @@ import java.util.List;
import org.killbill.billing.invoice.api.Invoice;
import org.killbill.billing.invoice.api.InvoiceItem;
+import org.killbill.billing.invoice.plugin.api.InvoiceContext;
import org.killbill.billing.invoice.plugin.api.NoOpInvoicePluginApi;
+import org.killbill.billing.invoice.plugin.api.OnFailureInvoiceResult;
+import org.killbill.billing.invoice.plugin.api.OnSuccessInvoiceResult;
+import org.killbill.billing.invoice.plugin.api.PriorInvoiceResult;
import org.killbill.billing.payment.api.PluginProperty;
import org.killbill.billing.util.callcontext.CallContext;
-import org.killbill.clock.Clock;
import com.google.common.collect.ImmutableList;
import com.google.inject.Inject;
@@ -35,7 +39,22 @@ public class DefaultNoOpInvoiceProviderPlugin implements NoOpInvoicePluginApi {
}
@Override
- public List<InvoiceItem> getAdditionalInvoiceItems(final Invoice invoice, final boolean isDryRun, final Iterable<PluginProperty> properties, CallContext context) {
+ public PriorInvoiceResult priorCall(final InvoiceContext invoiceContext, final Iterable<PluginProperty> properties) {
+ return null;
+ }
+
+ @Override
+ public List<InvoiceItem> getAdditionalInvoiceItems(final Invoice invoice, final boolean isDryRun, final Iterable<PluginProperty> properties, final CallContext context) {
return ImmutableList.<InvoiceItem>of();
}
+
+ @Override
+ public OnSuccessInvoiceResult onSuccessCall(final InvoiceContext invoiceContext, final Iterable<PluginProperty> properties) {
+ return null;
+ }
+
+ @Override
+ public OnFailureInvoiceResult onFailureCall(final InvoiceContext invoiceContext, final Iterable<PluginProperty> properties) {
+ return null;
+ }
}
pom.xml 2(+1 -1)
diff --git a/pom.xml b/pom.xml
index 77e2b9d..33d1295 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@
<parent>
<artifactId>killbill-oss-parent</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.141.44</version>
+ <version>0.141.45-SNAPSHOT</version>
</parent>
<artifactId>killbill</artifactId>
<version>0.19.7-SNAPSHOT</version>