killbill-aplcache
Changes
invoice/src/main/java/org/killbill/billing/invoice/generator/UsageInvoiceItemGenerator.java 22(+14 -8)
invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalCapacityUsageInArrear.java 4(+3 -1)
invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableUsageInArrear.java 4(+3 -1)
invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalUsageInArrear.java 20(+17 -3)
invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalConsumableInArrear.java 4(+2 -2)
Details
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 9acff42..570d678 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
@@ -1367,6 +1367,17 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
});
}
+ @Override
+ public List<InvoiceTrackingModelDao> getTrackingsByDateRange(final LocalDate startDate, final LocalDate endDate, final InternalCallContext context) {
+ return transactionalSqlDao.execute(true, new EntitySqlDaoTransactionWrapper<List<InvoiceTrackingModelDao>>() {
+ @Override
+ public List<InvoiceTrackingModelDao> inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
+ final InvoiceTrackingSqlDao transactional = entitySqlDaoWrapperFactory.become(InvoiceTrackingSqlDao.class);
+ return transactional.getTrackingsByDateRange(startDate.toDate(), endDate.toDate(), context);
+ }
+ });
+ }
+
// PERF: fetch tags once. See also https://github.com/killbill/killbill/issues/720.
private List<Tag> getInvoicesTags(final InternalTenantContext context) {
return tagInternalApi.getTagsForAccountType(ObjectType.INVOICE, false, context);
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 0c45abb..f14ada8 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
@@ -40,6 +40,7 @@ import org.killbill.billing.util.entity.dao.EntityDao;
public interface InvoiceDao extends EntityDao<InvoiceModelDao, Invoice, InvoiceApiException> {
+
void createInvoice(final InvoiceModelDao invoice,
final Set<InvoiceTrackingModelDao> trackingIds,
final FutureAccountNotifications callbackDateTimePerSubscriptions,
@@ -222,4 +223,7 @@ public interface InvoiceDao extends EntityDao<InvoiceModelDao, Invoice, InvoiceA
* @throws InvoiceApiException if any unexpected error occurs
*/
List<InvoiceItemModelDao> getInvoiceItemsByParentInvoice(UUID parentInvoiceId, final InternalTenantContext context) throws InvoiceApiException;
+
+ List<InvoiceTrackingModelDao> getTrackingsByDateRange(LocalDate startDate, LocalDate endDate, InternalCallContext context);
+
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/generator/InvoiceWithMetadata.java b/invoice/src/main/java/org/killbill/billing/invoice/generator/InvoiceWithMetadata.java
index fc7b7cc..4351fe8 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/generator/InvoiceWithMetadata.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/generator/InvoiceWithMetadata.java
@@ -30,6 +30,7 @@ import org.killbill.billing.invoice.api.InvoiceItem;
import org.killbill.billing.invoice.api.InvoiceItemType;
import org.killbill.billing.invoice.model.DefaultInvoice;
+import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
@@ -114,6 +115,26 @@ public class InvoiceWithMetadata {
public LocalDate getRecordDate() {
return recordDate;
}
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof TrackingIds)) {
+ return false;
+ }
+ final TrackingIds that = (TrackingIds) o;
+ return Objects.equal(trackingId, that.trackingId) &&
+ Objects.equal(invoiceId, that.invoiceId) &&
+ Objects.equal(subscriptionId, that.subscriptionId) &&
+ Objects.equal(recordDate, that.recordDate);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(trackingId, invoiceId, subscriptionId, recordDate);
+ }
}
public static class SubscriptionFutureNotificationDates {
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/generator/UsageInvoiceItemGenerator.java b/invoice/src/main/java/org/killbill/billing/invoice/generator/UsageInvoiceItemGenerator.java
index ea05a90..6a97846 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/generator/UsageInvoiceItemGenerator.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/generator/UsageInvoiceItemGenerator.java
@@ -18,10 +18,12 @@
package org.killbill.billing.invoice.generator;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
@@ -39,6 +41,7 @@ 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.generator.InvoiceWithMetadata.SubscriptionFutureNotificationDates;
+import org.killbill.billing.invoice.generator.InvoiceWithMetadata.TrackingIds;
import org.killbill.billing.invoice.usage.RawUsageOptimizer;
import org.killbill.billing.invoice.usage.RawUsageOptimizer.RawUsageOptimizerResult;
import org.killbill.billing.invoice.usage.SubscriptionUsageInArrear;
@@ -89,10 +92,11 @@ public class UsageInvoiceItemGenerator extends InvoiceItemGenerator {
final UsageDetailMode usageDetailMode = invoiceConfig.getItemResultBehaviorMode(internalCallContext);
final LocalDate minBillingEventDate = getMinBillingEventDate(eventSet, internalCallContext);
+ final Set<TrackingIds> trackingIds = new HashSet<>();
final List<InvoiceItem> items = Lists.newArrayList();
final Iterator<BillingEvent> events = eventSet.iterator();
- RawUsageOptimizerResult rawUsageOptimizerResult = null;
+ RawUsageOptimizerResult rawUsgRes = null;
List<BillingEvent> curEvents = Lists.newArrayList();
UUID curSubscriptionId = null;
while (events.hasNext()) {
@@ -104,29 +108,31 @@ public class UsageInvoiceItemGenerator extends InvoiceItemGenerator {
}
// Optimize to do the usage query only once after we know there are indeed some usage items
- if (rawUsageOptimizerResult == null &&
+ if (rawUsgRes == null &&
Iterables.any(event.getUsages(), new Predicate<Usage>() {
@Override
public boolean apply(@Nullable final Usage input) {
return input.getBillingMode() == BillingMode.IN_ARREAR;
}
})) {
- rawUsageOptimizerResult = rawUsageOptimizer.getInArrearUsage(minBillingEventDate, targetDate, Iterables.concat(perSubscriptionInArrearUsageItems.values()), eventSet.getUsages(), internalCallContext);
+ rawUsgRes = rawUsageOptimizer.getInArrearUsage(minBillingEventDate, targetDate, Iterables.concat(perSubscriptionInArrearUsageItems.values()), eventSet.getUsages(), internalCallContext);
}
// None of the billing events report any usage IN_ARREAR sections
- if (rawUsageOptimizerResult == null) {
+ if (rawUsgRes == null) {
continue;
}
final UUID subscriptionId = event.getSubscription().getId();
if (curSubscriptionId != null && !curSubscriptionId.equals(subscriptionId)) {
- final SubscriptionUsageInArrear subscriptionUsageInArrear = new SubscriptionUsageInArrear(account.getId(), invoiceId, curEvents, rawUsageOptimizerResult.getRawUsage(), targetDate, rawUsageOptimizerResult.getRawUsageStartDate(), usageDetailMode, internalCallContext);
+ final SubscriptionUsageInArrear subscriptionUsageInArrear = new SubscriptionUsageInArrear(account.getId(), invoiceId, curEvents, rawUsgRes.getRawUsage(), rawUsgRes.getExistingTrackingIds(), targetDate, rawUsgRes.getRawUsageStartDate(), usageDetailMode, internalCallContext);
final List<InvoiceItem> usageInArrearItems = perSubscriptionInArrearUsageItems.get(curSubscriptionId);
final SubscriptionUsageInArrearItemsAndNextNotificationDate subscriptionResult = subscriptionUsageInArrear.computeMissingUsageInvoiceItems(usageInArrearItems != null ? usageInArrearItems : ImmutableList.<InvoiceItem>of(), invoiceItemGeneratorLogger);
final List<InvoiceItem> newInArrearUsageItems = subscriptionResult.getInvoiceItems();
items.addAll(newInArrearUsageItems);
+ trackingIds.addAll(subscriptionResult.getTrackingIds());
+
updatePerSubscriptionNextNotificationUsageDate(curSubscriptionId, subscriptionResult.getPerUsageNotificationDates(), BillingMode.IN_ARREAR, perSubscriptionFutureNotificationDates);
curEvents = Lists.newArrayList();
}
@@ -134,18 +140,18 @@ public class UsageInvoiceItemGenerator extends InvoiceItemGenerator {
curEvents.add(event);
}
if (curSubscriptionId != null) {
- final SubscriptionUsageInArrear subscriptionUsageInArrear = new SubscriptionUsageInArrear(account.getId(), invoiceId, curEvents, rawUsageOptimizerResult.getRawUsage(), targetDate, rawUsageOptimizerResult.getRawUsageStartDate(), usageDetailMode, internalCallContext);
+ final SubscriptionUsageInArrear subscriptionUsageInArrear = new SubscriptionUsageInArrear(account.getId(), invoiceId, curEvents, rawUsgRes.getRawUsage(), rawUsgRes.getExistingTrackingIds(), targetDate, rawUsgRes.getRawUsageStartDate(), usageDetailMode, internalCallContext);
final List<InvoiceItem> usageInArrearItems = perSubscriptionInArrearUsageItems.get(curSubscriptionId);
final SubscriptionUsageInArrearItemsAndNextNotificationDate subscriptionResult = subscriptionUsageInArrear.computeMissingUsageInvoiceItems(usageInArrearItems != null ? usageInArrearItems : ImmutableList.<InvoiceItem>of(), invoiceItemGeneratorLogger);
final List<InvoiceItem> newInArrearUsageItems = subscriptionResult.getInvoiceItems();
items.addAll(newInArrearUsageItems);
+ trackingIds.addAll(subscriptionResult.getTrackingIds());
updatePerSubscriptionNextNotificationUsageDate(curSubscriptionId, subscriptionResult.getPerUsageNotificationDates(), BillingMode.IN_ARREAR, perSubscriptionFutureNotificationDates);
}
-
invoiceItemGeneratorLogger.logItems();
- return new InvoiceGeneratorResult(items, ImmutableSet.of());
+ return new InvoiceGeneratorResult(items, trackingIds);
} catch (final CatalogApiException e) {
throw new InvoiceApiException(e);
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalCapacityUsageInArrear.java b/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalCapacityUsageInArrear.java
index a55c0bf..82e7040 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalCapacityUsageInArrear.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalCapacityUsageInArrear.java
@@ -32,6 +32,7 @@ import org.killbill.billing.catalog.api.Tier;
import org.killbill.billing.catalog.api.Usage;
import org.killbill.billing.invoice.api.InvoiceApiException;
import org.killbill.billing.invoice.api.InvoiceItem;
+import org.killbill.billing.invoice.generator.InvoiceWithMetadata.TrackingIds;
import org.killbill.billing.invoice.model.UsageInvoiceItem;
import org.killbill.billing.invoice.usage.details.UsageCapacityInArrearAggregate;
import org.killbill.billing.invoice.usage.details.UsageInArrearAggregate;
@@ -55,11 +56,12 @@ public class ContiguousIntervalCapacityUsageInArrear extends ContiguousIntervalU
final UUID accountId,
final UUID invoiceId,
final List<RawUsage> rawSubscriptionUsage,
+ final List<TrackingIds> existingTrackingId,
final LocalDate targetDate,
final LocalDate rawUsageStartDate,
final UsageDetailMode usageDetailMode,
final InternalTenantContext internalTenantContext) {
- super(usage, accountId, invoiceId, rawSubscriptionUsage, targetDate, rawUsageStartDate, usageDetailMode, internalTenantContext);
+ super(usage, accountId, invoiceId, rawSubscriptionUsage, existingTrackingId, targetDate, rawUsageStartDate, usageDetailMode, internalTenantContext);
}
@Override
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableUsageInArrear.java b/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableUsageInArrear.java
index 22e812c..43f2ecf 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableUsageInArrear.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableUsageInArrear.java
@@ -36,6 +36,7 @@ import org.killbill.billing.catalog.api.TieredBlock;
import org.killbill.billing.catalog.api.Usage;
import org.killbill.billing.invoice.api.InvoiceApiException;
import org.killbill.billing.invoice.api.InvoiceItem;
+import org.killbill.billing.invoice.generator.InvoiceWithMetadata.TrackingIds;
import org.killbill.billing.invoice.model.UsageInvoiceItem;
import org.killbill.billing.invoice.usage.details.UsageConsumableInArrearAggregate;
import org.killbill.billing.invoice.usage.details.UsageConsumableInArrearTierUnitAggregate;
@@ -64,11 +65,12 @@ public class ContiguousIntervalConsumableUsageInArrear extends ContiguousInterva
final UUID accountId,
final UUID invoiceId,
final List<RawUsage> rawSubscriptionUsage,
+ final List<TrackingIds> existingTrackingId,
final LocalDate targetDate,
final LocalDate rawUsageStartDate,
final UsageDetailMode usageDetailMode,
final InternalTenantContext internalTenantContext) {
- super(usage, accountId, invoiceId, rawSubscriptionUsage, targetDate, rawUsageStartDate, usageDetailMode, internalTenantContext);
+ super(usage, accountId, invoiceId, rawSubscriptionUsage, existingTrackingId, targetDate, rawUsageStartDate, usageDetailMode, internalTenantContext);
}
@Override
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalUsageInArrear.java b/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalUsageInArrear.java
index 98def8c..bb40b12 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalUsageInArrear.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalUsageInArrear.java
@@ -20,6 +20,7 @@ package org.killbill.billing.invoice.usage;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -40,6 +41,7 @@ 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.generator.BillingIntervalDetail;
+import org.killbill.billing.invoice.generator.InvoiceWithMetadata.TrackingIds;
import org.killbill.billing.invoice.model.UsageInvoiceItem;
import org.killbill.billing.invoice.usage.details.UsageInArrearAggregate;
import org.killbill.billing.junction.BillingEvent;
@@ -56,6 +58,7 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@@ -76,6 +79,7 @@ public abstract class ContiguousIntervalUsageInArrear {
protected final Usage usage;
protected final Set<String> unitTypes;
protected final List<RawUsage> rawSubscriptionUsage;
+ protected final List<TrackingIds> existingTrackingId;
protected final LocalDate targetDate;
protected final UUID accountId;
protected final UUID invoiceId;
@@ -89,6 +93,7 @@ public abstract class ContiguousIntervalUsageInArrear {
final UUID accountId,
final UUID invoiceId,
final List<RawUsage> rawSubscriptionUsage,
+ final List<TrackingIds> existingTrackingIds,
final LocalDate targetDate,
final LocalDate rawUsageStartDate,
final UsageDetailMode usageDetailMode,
@@ -98,6 +103,7 @@ public abstract class ContiguousIntervalUsageInArrear {
this.invoiceId = invoiceId;
this.unitTypes = usage.getUsageType() == UsageType.CAPACITY ? getCapacityInArrearUnitTypes(usage) : getConsumableInArrearUnitTypes(usage);
this.rawSubscriptionUsage = filterInputRawUsage(rawSubscriptionUsage);
+ this.existingTrackingId = existingTrackingIds;
this.targetDate = targetDate;
this.rawUsageStartDate = rawUsageStartDate;
this.internalTenantContext = internalTenantContext;
@@ -166,9 +172,10 @@ public abstract class ContiguousIntervalUsageInArrear {
Preconditions.checkState(isBuilt.get());
if (transitionTimes.size() < 2) {
- return new UsageInArrearItemsAndNextNotificationDate(ImmutableList.<InvoiceItem>of(), computeNextNotificationDate());
+ return new UsageInArrearItemsAndNextNotificationDate(ImmutableList.<InvoiceItem>of(), ImmutableSet.of(), computeNextNotificationDate());
}
+ final Set<TrackingIds> trackingIds = new HashSet<TrackingIds>();
final List<InvoiceItem> result = Lists.newLinkedList();
final List<RolledUpUsage> allUsage = getRolledUpUsage();
// Each RolledUpUsage 'ru' is for a specific time period and across all units
@@ -193,7 +200,7 @@ public abstract class ContiguousIntervalUsageInArrear {
populateResults(ru.getStart(), ru.getEnd(), billedUsage, toBeBilledUsage, toBeBilledUsageDetails, areAllBilledItemsWithDetails, isPeriodPreviouslyBilled, result);
}
final LocalDate nextNotificationDate = computeNextNotificationDate();
- return new UsageInArrearItemsAndNextNotificationDate(result, nextNotificationDate);
+ return new UsageInArrearItemsAndNextNotificationDate(result, trackingIds, nextNotificationDate);
}
protected abstract void populateResults(final LocalDate startDate, final LocalDate endDate, final BigDecimal billedUsage, final BigDecimal toBeBilledUsage, final UsageInArrearAggregate toBeBilledUsageDetails, final boolean areAllBilledItemsWithDetails, final boolean isPeriodPreviouslyBilled, final List<InvoiceItem> result) throws InvoiceApiException;
@@ -447,10 +454,13 @@ public abstract class ContiguousIntervalUsageInArrear {
private final List<InvoiceItem> invoiceItems;
private final LocalDate nextNotificationDate;
+ private final Set<TrackingIds> trackingIds;
- public UsageInArrearItemsAndNextNotificationDate(final List<InvoiceItem> invoiceItems, final LocalDate nextNotificationDate) {
+
+ public UsageInArrearItemsAndNextNotificationDate(final List<InvoiceItem> invoiceItems, final Set<TrackingIds> trackingIds, final LocalDate nextNotificationDate) {
this.invoiceItems = invoiceItems;
this.nextNotificationDate = nextNotificationDate;
+ this.trackingIds = trackingIds;
}
public List<InvoiceItem> getInvoiceItems() {
@@ -460,6 +470,10 @@ public abstract class ContiguousIntervalUsageInArrear {
public LocalDate getNextNotificationDate() {
return nextNotificationDate;
}
+
+ public Set<TrackingIds> getTrackingIds() {
+ return trackingIds;
+ }
}
protected String toJson(final Object usageInArrearAggregate) {
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/usage/RawUsageOptimizer.java b/invoice/src/main/java/org/killbill/billing/invoice/usage/RawUsageOptimizer.java
index 1e513ee..e05e498 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/usage/RawUsageOptimizer.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/usage/RawUsageOptimizer.java
@@ -30,7 +30,10 @@ import org.killbill.billing.callcontext.InternalCallContext;
import org.killbill.billing.catalog.api.BillingPeriod;
import org.killbill.billing.catalog.api.Usage;
import org.killbill.billing.invoice.api.InvoiceItem;
+import org.killbill.billing.invoice.dao.InvoiceDao;
+import org.killbill.billing.invoice.dao.InvoiceTrackingModelDao;
import org.killbill.billing.invoice.generator.InvoiceDateUtils;
+import org.killbill.billing.invoice.generator.InvoiceWithMetadata.TrackingIds;
import org.killbill.billing.invoice.model.UsageInvoiceItem;
import org.killbill.billing.usage.InternalUserApi;
import org.killbill.billing.usage.RawUsage;
@@ -41,6 +44,7 @@ import org.slf4j.LoggerFactory;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;
@@ -59,11 +63,13 @@ public class RawUsageOptimizer {
private final InternalUserApi usageApi;
private final InvoiceConfig config;
+ private final InvoiceDao invoiceDao;
@Inject
- public RawUsageOptimizer(final InvoiceConfig config, final InternalUserApi usageApi) {
+ public RawUsageOptimizer(final InvoiceConfig config, final InvoiceDao invoiceDao, final InternalUserApi usageApi) {
this.usageApi = usageApi;
this.config = config;
+ this.invoiceDao = invoiceDao;
}
public RawUsageOptimizerResult getInArrearUsage(final LocalDate firstEventStartDate, final LocalDate targetDate, final Iterable<InvoiceItem> existingUsageItems, final Map<String, Usage> knownUsage, final InternalCallContext internalCallContext) {
@@ -71,7 +77,15 @@ public class RawUsageOptimizer {
log.debug("ConsumableInArrear accountRecordId='{}', rawUsageStartDate='{}', firstEventStartDate='{}'",
internalCallContext.getAccountRecordId(), targetStartDate, firstEventStartDate);
final List<RawUsage> rawUsageData = usageApi.getRawUsageForAccount(targetStartDate, targetDate, internalCallContext);
- return new RawUsageOptimizerResult(targetStartDate, rawUsageData);
+
+ final List<InvoiceTrackingModelDao> trackingIds = invoiceDao.getTrackingsByDateRange(targetStartDate, targetDate, internalCallContext);
+ final List<TrackingIds> existingTrackingIds = ImmutableList.copyOf(Iterables.transform(trackingIds, new Function<InvoiceTrackingModelDao, TrackingIds>() {
+ @Override
+ public TrackingIds apply(final InvoiceTrackingModelDao input) {
+ return new TrackingIds(input.getTrackingId(), input.getInvoiceId(), input.getSubscriptionId(), input.getRecordDate());
+ }
+ }));
+ return new RawUsageOptimizerResult(targetStartDate, rawUsageData, existingTrackingIds);
}
@VisibleForTesting
@@ -153,10 +167,12 @@ public class RawUsageOptimizer {
private final LocalDate rawUsageStartDate;
private final List<RawUsage> rawUsage;
+ private final List<TrackingIds> existingTrackingIds;
- public RawUsageOptimizerResult(final LocalDate rawUsageStartDate, final List<RawUsage> rawUsage) {
+ public RawUsageOptimizerResult(final LocalDate rawUsageStartDate, final List<RawUsage> rawUsage, final List<TrackingIds> existingTrackingIds) {
this.rawUsageStartDate = rawUsageStartDate;
this.rawUsage = rawUsage;
+ this.existingTrackingIds = existingTrackingIds;
}
public LocalDate getRawUsageStartDate() {
@@ -166,5 +182,9 @@ public class RawUsageOptimizer {
public List<RawUsage> getRawUsage() {
return rawUsage;
}
+
+ public List<TrackingIds> getExistingTrackingIds() {
+ return existingTrackingIds;
+ }
}
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/usage/SubscriptionUsageInArrear.java b/invoice/src/main/java/org/killbill/billing/invoice/usage/SubscriptionUsageInArrear.java
index bb3d830..af2b98a 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/usage/SubscriptionUsageInArrear.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/usage/SubscriptionUsageInArrear.java
@@ -37,10 +37,10 @@ import org.killbill.billing.catalog.api.UsageType;
import org.killbill.billing.invoice.api.InvoiceApiException;
import org.killbill.billing.invoice.api.InvoiceItem;
import org.killbill.billing.invoice.generator.InvoiceItemGenerator.InvoiceItemGeneratorLogger;
+import org.killbill.billing.invoice.generator.InvoiceWithMetadata.TrackingIds;
import org.killbill.billing.invoice.usage.ContiguousIntervalUsageInArrear.UsageInArrearItemsAndNextNotificationDate;
import org.killbill.billing.junction.BillingEvent;
import org.killbill.billing.usage.RawUsage;
-import org.killbill.billing.util.config.definition.InvoiceConfig;
import org.killbill.billing.util.config.definition.InvoiceConfig.UsageDetailMode;
import com.google.common.annotations.VisibleForTesting;
@@ -80,6 +80,7 @@ public class SubscriptionUsageInArrear {
private final List<BillingEvent> subscriptionBillingEvents;
private final LocalDate targetDate;
private final List<RawUsage> rawSubscriptionUsage;
+ private final List<TrackingIds> existingTrackingIds;
private final LocalDate rawUsageStartDate;
private final InternalTenantContext internalTenantContext;
private final UsageDetailMode usageDetailMode;
@@ -88,6 +89,7 @@ public class SubscriptionUsageInArrear {
final UUID invoiceId,
final List<BillingEvent> subscriptionBillingEvents,
final List<RawUsage> rawUsage,
+ final List<TrackingIds> existingTrackingIds,
final LocalDate targetDate,
final LocalDate rawUsageStartDate,
final UsageDetailMode usageDetailMode,
@@ -106,6 +108,7 @@ public class SubscriptionUsageInArrear {
return input.getSubscriptionId().equals(subscriptionBillingEvents.get(0).getSubscription().getId());
}
}));
+ this.existingTrackingIds = existingTrackingIds;
this.usageDetailMode = usageDetailMode;
}
@@ -125,6 +128,7 @@ public class SubscriptionUsageInArrear {
invoiceItemGeneratorLogger.append(usageInterval, newItemsWithDetailsAndDate.getInvoiceItems());
result.addUsageInArrearItemsAndNextNotificationDate(usageInterval.getUsage().getName(), newItemsWithDetailsAndDate);
+ result.addTrackingIds(newItemsWithDetailsAndDate.getTrackingIds());
}
return result;
}
@@ -161,8 +165,8 @@ public class SubscriptionUsageInArrear {
ContiguousIntervalUsageInArrear existingInterval = inFlightInArrearUsageIntervals.get(usageKey);
if (existingInterval == null) {
existingInterval = usage.getUsageType() == UsageType.CAPACITY ?
- new ContiguousIntervalCapacityUsageInArrear(usage, accountId, invoiceId, rawSubscriptionUsage, targetDate, rawUsageStartDate, usageDetailMode, internalTenantContext) :
- new ContiguousIntervalConsumableUsageInArrear(usage, accountId, invoiceId, rawSubscriptionUsage, targetDate, rawUsageStartDate, usageDetailMode, internalTenantContext);
+ new ContiguousIntervalCapacityUsageInArrear(usage, accountId, invoiceId, rawSubscriptionUsage, existingTrackingIds, targetDate, rawUsageStartDate, usageDetailMode, internalTenantContext) :
+ new ContiguousIntervalConsumableUsageInArrear(usage, accountId, invoiceId, rawSubscriptionUsage, existingTrackingIds, targetDate, rawUsageStartDate, usageDetailMode, internalTenantContext);
inFlightInArrearUsageIntervals.put(usageKey, existingInterval);
}
@@ -207,6 +211,7 @@ public class SubscriptionUsageInArrear {
private List<InvoiceItem> invoiceItems;
private Map<String, LocalDate> perUsageNotificationDates;
+ private Set<TrackingIds> trackingIds;
public SubscriptionUsageInArrearItemsAndNextNotificationDate() {
this.invoiceItems = null;
@@ -230,6 +235,14 @@ public class SubscriptionUsageInArrear {
}
}
+ public void addTrackingIds(final Set<TrackingIds> input) {
+ if (trackingIds == null) {
+ trackingIds = new HashSet<>();
+ }
+ trackingIds.addAll(input);
+
+ }
+
public List<InvoiceItem> getInvoiceItems() {
return invoiceItems != null ? invoiceItems : ImmutableList.<InvoiceItem>of();
}
@@ -237,6 +250,10 @@ public class SubscriptionUsageInArrear {
public Map<String, LocalDate> getPerUsageNotificationDates() {
return perUsageNotificationDates != null ? perUsageNotificationDates : ImmutableMap.<String, LocalDate>of();
}
+
+ public Set<TrackingIds> getTrackingIds() {
+ return trackingIds;
+ }
}
private static class UsageKey {
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 2833ec5..c76d135 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
@@ -437,4 +437,9 @@ public class MockInvoiceDao extends MockEntityDaoBase<InvoiceModelDao, Invoice,
public List<InvoiceItemModelDao> getInvoiceItemsByParentInvoice(final UUID parentInvoiceId, final InternalTenantContext context) throws InvoiceApiException {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public List<InvoiceTrackingModelDao> getTrackingsByDateRange(final LocalDate startDate, final LocalDate endDate, final InternalCallContext context) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalConsumableInArrear.java b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalConsumableInArrear.java
index 290bb21..25bce46 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalConsumableInArrear.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalConsumableInArrear.java
@@ -516,8 +516,8 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
final BillingEvent event2 = createMockBillingEvent(new LocalDate(2014, 10, 16).toDateTimeAtStartOfDay(DateTimeZone.UTC), BillingPeriod.MONTHLY, Collections.<Usage>emptyList());
final ContiguousIntervalUsageInArrear intervalConsumableInArrear = usage.getUsageType() == UsageType.CAPACITY ?
- new ContiguousIntervalCapacityUsageInArrear(usage, accountId, invoiceId, rawUsages, targetDate, rawUsageStartDate, usageDetailMode, internalCallContext) :
- new ContiguousIntervalConsumableUsageInArrear(usage, accountId, invoiceId, rawUsages, targetDate, rawUsageStartDate, usageDetailMode, internalCallContext);
+ new ContiguousIntervalCapacityUsageInArrear(usage, accountId, invoiceId, rawUsages, EMPTY_EXISTING_TRACKING_IDS, targetDate, rawUsageStartDate, usageDetailMode, internalCallContext) :
+ new ContiguousIntervalConsumableUsageInArrear(usage, accountId, invoiceId, rawUsages, EMPTY_EXISTING_TRACKING_IDS, targetDate, rawUsageStartDate, usageDetailMode, internalCallContext);
intervalConsumableInArrear.addBillingEvent(event1);
intervalConsumableInArrear.addBillingEvent(event2);
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestSubscriptionConsumableInArrear.java b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestSubscriptionConsumableInArrear.java
index c9fe78b..43612e6 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestSubscriptionConsumableInArrear.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestSubscriptionConsumableInArrear.java
@@ -70,7 +70,7 @@ public class TestSubscriptionConsumableInArrear extends TestUsageInArrearBase {
LocalDate targetDate = new LocalDate(2013, 6, 23);
- final SubscriptionUsageInArrear foo = new SubscriptionUsageInArrear(accountId, invoiceId, billingEvents, ImmutableList.<RawUsage>of(), targetDate, new LocalDate(dt1, DateTimeZone.UTC), usageDetailMode, internalCallContext);
+ final SubscriptionUsageInArrear foo = new SubscriptionUsageInArrear(accountId, invoiceId, billingEvents, ImmutableList.<RawUsage>of(), ImmutableList.of(), targetDate, new LocalDate(dt1, DateTimeZone.UTC), usageDetailMode, internalCallContext);
final List<ContiguousIntervalUsageInArrear> result = foo.computeInArrearUsageInterval();
assertEquals(result.size(), 3);
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestUsageInArrearBase.java b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestUsageInArrearBase.java
index 75b5825..0ef0910 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestUsageInArrearBase.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestUsageInArrearBase.java
@@ -41,6 +41,7 @@ import org.killbill.billing.catalog.api.TierBlockPolicy;
import org.killbill.billing.catalog.api.Usage;
import org.killbill.billing.catalog.api.UsageType;
import org.killbill.billing.invoice.InvoiceTestSuiteNoDB;
+import org.killbill.billing.invoice.generator.InvoiceWithMetadata.TrackingIds;
import org.killbill.billing.junction.BillingEvent;
import org.killbill.billing.subscription.api.SubscriptionBase;
import org.killbill.billing.usage.RawUsage;
@@ -49,10 +50,13 @@ import org.killbill.billing.util.jackson.ObjectMapper;
import org.mockito.Mockito;
import org.testng.annotations.BeforeClass;
+import com.google.common.collect.ImmutableList;
+
public abstract class TestUsageInArrearBase extends InvoiceTestSuiteNoDB {
protected static final String DEFAULT_TRACKING_ID = "_tracking_id_missing";
+ protected static final List<TrackingIds> EMPTY_EXISTING_TRACKING_IDS = ImmutableList.of();
protected int BCD;
protected UUID accountId;
@@ -94,7 +98,7 @@ public abstract class TestUsageInArrearBase extends InvoiceTestSuiteNoDB {
}
protected ContiguousIntervalCapacityUsageInArrear createContiguousIntervalCapacityInArrear(final DefaultUsage usage, final List<RawUsage> rawUsages, final LocalDate targetDate, final boolean closedInterval, UsageDetailMode detailMode, final BillingEvent... events) {
- final ContiguousIntervalCapacityUsageInArrear intervalCapacityInArrear = new ContiguousIntervalCapacityUsageInArrear(usage, accountId, invoiceId, rawUsages, targetDate, new LocalDate(events[0].getEffectiveDate()), detailMode, internalCallContext);
+ final ContiguousIntervalCapacityUsageInArrear intervalCapacityInArrear = new ContiguousIntervalCapacityUsageInArrear(usage, accountId, invoiceId, rawUsages, EMPTY_EXISTING_TRACKING_IDS, targetDate, new LocalDate(events[0].getEffectiveDate()), detailMode, internalCallContext);
for (final BillingEvent event : events) {
intervalCapacityInArrear.addBillingEvent(event);
}
@@ -108,7 +112,7 @@ public abstract class TestUsageInArrearBase extends InvoiceTestSuiteNoDB {
}
protected ContiguousIntervalConsumableUsageInArrear createContiguousIntervalConsumableInArrear(final DefaultUsage usage, final List<RawUsage> rawUsages, final LocalDate targetDate, final boolean closedInterval, UsageDetailMode detailMode, final BillingEvent... events) {
- final ContiguousIntervalConsumableUsageInArrear intervalConsumableInArrear = new ContiguousIntervalConsumableUsageInArrear(usage, accountId, invoiceId, rawUsages, targetDate, new LocalDate(events[0].getEffectiveDate()), detailMode, internalCallContext);
+ final ContiguousIntervalConsumableUsageInArrear intervalConsumableInArrear = new ContiguousIntervalConsumableUsageInArrear(usage, accountId, invoiceId, rawUsages, EMPTY_EXISTING_TRACKING_IDS, targetDate, new LocalDate(events[0].getEffectiveDate()), detailMode, internalCallContext);
for (final BillingEvent event : events) {
intervalConsumableInArrear.addBillingEvent(event);
}