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 bf84173..252e4ae 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
@@ -86,6 +86,7 @@ import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
@@ -309,20 +310,21 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
final FutureAccountNotifications callbackDateTimePerSubscriptions,
final ExistingInvoiceMetadata existingInvoiceMetadata,
final InternalCallContext context) {
- createInvoices(ImmutableList.<InvoiceModelDao>of(invoice), trackingIds, callbackDateTimePerSubscriptions, existingInvoiceMetadata, context);
+ createInvoices(ImmutableList.<InvoiceModelDao>of(invoice), trackingIds, callbackDateTimePerSubscriptions, existingInvoiceMetadata, false, context);
}
@Override
public List<InvoiceItemModelDao> createInvoices(final List<InvoiceModelDao> invoices,
final Set<InvoiceTrackingModelDao> trackingIds,
final InternalCallContext context) {
- return createInvoices(invoices, trackingIds, new FutureAccountNotifications(), null, context);
+ return createInvoices(invoices, trackingIds, new FutureAccountNotifications(), null, true, context);
}
private List<InvoiceItemModelDao> createInvoices(final Iterable<InvoiceModelDao> invoices,
final Set<InvoiceTrackingModelDao> trackingIds,
final FutureAccountNotifications callbackDateTimePerSubscriptions,
@Nullable final ExistingInvoiceMetadata existingInvoiceMetadataOrNull,
+ final boolean returnCreatedInvoiceItems,
final InternalCallContext context) {
// Track invoices that are being created
final Collection<UUID> createdInvoiceIds = new HashSet<UUID>();
@@ -361,7 +363,7 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
existingInvoiceMetadata = existingInvoiceMetadataOrNull;
}
- final List<InvoiceItemModelDao> invoiceItemsToCreate = new LinkedList<InvoiceItemModelDao>();
+ final Collection<InvoiceItemModelDao> invoiceItemsToCreate = new LinkedList<InvoiceItemModelDao>();
for (final InvoiceModelDao invoiceModelDao : invoices) {
invoiceByInvoiceId.put(invoiceModelDao.getId(), invoiceModelDao);
final boolean isNotShellInvoice = invoiceIdsReferencedFromItems.remove(invoiceModelDao.getId());
@@ -414,7 +416,7 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
}
// Bulk insert the invoice items
- final List<InvoiceItemModelDao> createdInvoiceItems = createInvoiceItemsFromTransaction(transInvoiceItemSqlDao, invoiceItemsToCreate, context);
+ createInvoiceItemsFromTransaction(transInvoiceItemSqlDao, invoiceItemsToCreate, context);
for (final UUID adjustedInvoiceId : allInvoiceIds) {
final boolean newInvoice = createdInvoiceIds.contains(adjustedInvoiceId);
@@ -438,7 +440,22 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
trackingIdsSqlDao.create(trackingIds, context);
}
- return createdInvoiceItems;
+ if (returnCreatedInvoiceItems) {
+ if (invoiceItemsToCreate.isEmpty()) {
+ return ImmutableList.<InvoiceItemModelDao>of();
+ } else {
+ return transInvoiceItemSqlDao.getByIds(Collections2.<InvoiceItemModelDao, String>transform(invoiceItemsToCreate,
+ new Function<InvoiceItemModelDao, String>() {
+ @Override
+ public String apply(final InvoiceItemModelDao input) {
+ return input.getId().toString();
+ }
+ }),
+ context);
+ }
+ } else {
+ return null;
+ }
}
});
}
@@ -1134,25 +1151,31 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
}
}
- private InvoiceItemModelDao createInvoiceItemFromTransaction(final InvoiceItemSqlDao invoiceItemSqlDao,
- final InvoiceItemModelDao invoiceItemModelDao,
- final InternalCallContext context) throws EntityPersistenceException, InvoiceApiException {
- return Iterables.<InvoiceItemModelDao>getFirst(createInvoiceItemsFromTransaction(invoiceItemSqlDao, ImmutableList.<InvoiceItemModelDao>of(invoiceItemModelDao), context), null);
+ private void createInvoiceItemFromTransaction(final InvoiceItemSqlDao invoiceItemSqlDao,
+ final InvoiceItemModelDao invoiceItemModelDao,
+ final InternalCallContext context) throws EntityPersistenceException, InvoiceApiException {
+ validateInvoiceItemToBeAdjustedIfNeeded(invoiceItemSqlDao, invoiceItemModelDao, context);
+
+ createAndRefresh(invoiceItemSqlDao, invoiceItemModelDao, context);
}
- private List<InvoiceItemModelDao> createInvoiceItemsFromTransaction(final InvoiceItemSqlDao invoiceItemSqlDao,
- final Iterable<InvoiceItemModelDao> invoiceItemModelDaos,
- final InternalCallContext context) throws EntityPersistenceException, InvoiceApiException {
+ private void createInvoiceItemsFromTransaction(final InvoiceItemSqlDao invoiceItemSqlDao,
+ final Iterable<InvoiceItemModelDao> invoiceItemModelDaos,
+ final InternalCallContext context) throws EntityPersistenceException, InvoiceApiException {
for (final InvoiceItemModelDao invoiceItemModelDao : invoiceItemModelDaos) {
- // There is no efficient way to retrieve an invoice item given an ID today (and invoice plugins can put item adjustments
- // on a different invoice than the original item), so it's easier to do the check in the DAO rather than in the API layer
- // See also https://github.com/killbill/killbill/issues/7
- if (InvoiceItemType.ITEM_ADJ.equals(invoiceItemModelDao.getType())) {
- validateInvoiceItemToBeAdjusted(invoiceItemSqlDao, invoiceItemModelDao, context);
- }
+ validateInvoiceItemToBeAdjustedIfNeeded(invoiceItemSqlDao, invoiceItemModelDao, context);
}
- return createAndRefresh(invoiceItemSqlDao, invoiceItemModelDaos, context);
+ bulkCreate(invoiceItemSqlDao, invoiceItemModelDaos, context);
+ }
+
+ private void validateInvoiceItemToBeAdjustedIfNeeded(final InvoiceItemSqlDao invoiceItemSqlDao, final InvoiceItemModelDao invoiceItemModelDao, final InternalCallContext context) throws InvoiceApiException {
+ // There is no efficient way to retrieve an invoice item given an ID today (and invoice plugins can put item adjustments
+ // on a different invoice than the original item), so it's easier to do the check in the DAO rather than in the API layer
+ // See also https://github.com/killbill/killbill/issues/7
+ if (InvoiceItemType.ITEM_ADJ.equals(invoiceItemModelDao.getType())) {
+ validateInvoiceItemToBeAdjusted(invoiceItemSqlDao, invoiceItemModelDao, context);
+ }
}
private void validateInvoiceItemToBeAdjusted(final InvoiceItemSqlDao invoiceItemSqlDao, final InvoiceItemModelDao invoiceItemModelDao, final InternalCallContext context) throws InvoiceApiException {
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 47fde47..b1533de 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
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2017 Groupon, Inc
- * Copyright 2014-2017 The Billing Project, LLC
+ * Copyright 2014-2019 Groupon, Inc
+ * Copyright 2014-2019 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
@@ -19,6 +19,7 @@
package org.killbill.billing.invoice.dao;
import java.math.BigDecimal;
+import java.util.Collection;
import java.util.List;
import org.killbill.billing.callcontext.InternalCallContext;
@@ -32,6 +33,7 @@ import org.killbill.commons.jdbi.template.KillBillSqlDaoStringTemplate;
import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.unstable.BindIn;
@KillBillSqlDaoStringTemplate
public interface InvoiceItemSqlDao extends EntitySqlDao<InvoiceItemModelDao, InvoiceItem> {
@@ -39,14 +41,14 @@ public interface InvoiceItemSqlDao extends EntitySqlDao<InvoiceItemModelDao, Inv
@SqlQuery
List<InvoiceItemModelDao> getInvoiceItemsByInvoice(@Bind("invoiceId") final String invoiceId,
@SmartBindBean final InternalTenantContext context);
+
@SqlQuery
List<InvoiceItemModelDao> getInvoiceItemsBySubscription(@Bind("subscriptionId") final String subscriptionId,
@SmartBindBean final InternalTenantContext context);
-
@SqlQuery
List<InvoiceItemModelDao> getAdjustedOrRepairedInvoiceItemsByLinkedId(@Bind("linkedItemId") final String linkedItemId,
- @SmartBindBean final InternalTenantContext context);
+ @SmartBindBean final InternalTenantContext context);
@SqlUpdate
@Audited(ChangeType.UPDATE)
@@ -62,4 +64,8 @@ public interface InvoiceItemSqlDao extends EntitySqlDao<InvoiceItemModelDao, Inv
@SqlQuery
BigDecimal getAccountCBA(@SmartBindBean final InternalTenantContext context);
+
+ @SqlQuery
+ List<InvoiceItemModelDao> getByIds(@BindIn("ids") final Collection<String> invoiceItemIds,
+ @SmartBindBean final InternalTenantContext context);
}
diff --git a/util/src/main/java/org/killbill/billing/util/entity/dao/EntityDaoBase.java b/util/src/main/java/org/killbill/billing/util/entity/dao/EntityDaoBase.java
index b92af82..d58c367 100644
--- a/util/src/main/java/org/killbill/billing/util/entity/dao/EntityDaoBase.java
+++ b/util/src/main/java/org/killbill/billing/util/entity/dao/EntityDaoBase.java
@@ -28,7 +28,6 @@ import java.util.UUID;
import org.killbill.billing.BillingExceptionBase;
import org.killbill.billing.callcontext.InternalCallContext;
import org.killbill.billing.callcontext.InternalTenantContext;
-import org.killbill.billing.entity.EntityPersistenceException;
import org.killbill.billing.util.audit.ChangeType;
import org.killbill.billing.util.entity.DefaultPagination;
import org.killbill.billing.util.entity.Entity;
@@ -113,18 +112,17 @@ public abstract class EntityDaoBase<M extends EntityModelDao<E>, E extends Entit
};
}
- protected <F extends EntityModelDao> F createAndRefresh(final EntitySqlDao transactional, final F entity, final InternalCallContext context) throws EntityPersistenceException {
+ protected <F extends EntityModelDao> F createAndRefresh(final EntitySqlDao transactional, final F entity, final InternalCallContext context) {
// We have overridden the jDBI return type in EntitySqlDaoWrapperInvocationHandler
return (F) transactional.create(entity, context);
}
- protected <F extends EntityModelDao> List<F> createAndRefresh(final EntitySqlDao transactional, final Iterable<F> entities, final InternalCallContext context) throws EntityPersistenceException {
+ protected <F extends EntityModelDao> void bulkCreate(final EntitySqlDao transactional, final Iterable<F> entities, final InternalCallContext context) {
if (Iterables.<F>isEmpty(entities)) {
- return ImmutableList.<F>of();
+ return;
}
- // We have overridden the jDBI return type in EntitySqlDaoWrapperInvocationHandler
- return (List<F>) transactional.create(entities, context);
+ transactional.create(entities, context);
}
protected boolean checkEntityAlreadyExists(final EntitySqlDao<M, E> transactional, final M entity, final InternalCallContext context) {