killbill-memoizeit
Changes
invoice/src/main/java/org/killbill/billing/invoice/generator/FixedAndRecurringInvoiceItemGenerator.java 56(+30 -26)
invoice/src/main/java/org/killbill/billing/invoice/generator/UsageInvoiceItemGenerator.java 10(+7 -3)
invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableInArrear.java 10(+10 -0)
Details
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/generator/FixedAndRecurringInvoiceItemGenerator.java b/invoice/src/main/java/org/killbill/billing/invoice/generator/FixedAndRecurringInvoiceItemGenerator.java
index 1370254..f8787d7 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/generator/FixedAndRecurringInvoiceItemGenerator.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/generator/FixedAndRecurringInvoiceItemGenerator.java
@@ -100,16 +100,12 @@ public class FixedAndRecurringInvoiceItemGenerator extends InvoiceItemGenerator
final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDate,
@Nullable final List<Invoice> existingInvoices,
final InternalCallContext internalCallContext) throws InvoiceApiException {
- if (events.size() == 0) {
+ if (events.isEmpty()) {
return;
}
// Pretty-print the generated invoice items from the junction events
- final StringBuilder logStringBuilder = new StringBuilder("Proposed Invoice items for invoiceId='")
- .append(invoiceId)
- .append("', accountId='")
- .append(accountId)
- .append("'");
+ final InvoiceItemGeneratorLogger invoiceItemGeneratorLogger = new InvoiceItemGeneratorLogger(invoiceId, accountId, "recurring", log);
final Iterator<BillingEvent> eventIt = events.iterator();
BillingEvent nextEvent = eventIt.next();
@@ -119,29 +115,34 @@ public class FixedAndRecurringInvoiceItemGenerator extends InvoiceItemGenerator
if (!events.getSubscriptionIdsWithAutoInvoiceOff().
contains(thisEvent.getSubscription().getId())) { // don't consider events for subscriptions that have auto_invoice_off
final BillingEvent adjustedNextEvent = (thisEvent.getSubscription().getId() == nextEvent.getSubscription().getId()) ? nextEvent : null;
- final List<InvoiceItem> newProposedItems = processRecurringEvent(invoiceId, accountId, thisEvent, adjustedNextEvent, targetDate, currency, logStringBuilder, events.getRecurringBillingMode(), perSubscriptionFutureNotificationDate, internalCallContext);
+ final List<InvoiceItem> newProposedItems = processRecurringEvent(invoiceId, accountId, thisEvent, adjustedNextEvent, targetDate, currency, invoiceItemGeneratorLogger, events.getRecurringBillingMode(), perSubscriptionFutureNotificationDate, internalCallContext);
proposedItems.addAll(newProposedItems);
}
}
- final List<InvoiceItem> newProposedItems = processRecurringEvent(invoiceId, accountId, nextEvent, null, targetDate, currency, logStringBuilder, events.getRecurringBillingMode(), perSubscriptionFutureNotificationDate, internalCallContext);
+ final List<InvoiceItem> newProposedItems = processRecurringEvent(invoiceId, accountId, nextEvent, null, targetDate, currency, invoiceItemGeneratorLogger, events.getRecurringBillingMode(), perSubscriptionFutureNotificationDate, internalCallContext);
proposedItems.addAll(newProposedItems);
- log.info(logStringBuilder.toString());
-
- return;
+ invoiceItemGeneratorLogger.logItems();
}
@VisibleForTesting
void processFixedBillingEvents(final UUID invoiceId, final UUID accountId, final BillingEventSet events, final LocalDate targetDate,
final Currency currency, final List<InvoiceItem> proposedItems, final InternalCallContext internalCallContext) throws InvoiceApiException {
+ if (events.isEmpty()) {
+ return;
+ }
+
InvoiceItem prevItem = null;
+ // Pretty-print the generated invoice items from the junction events
+ final InvoiceItemGeneratorLogger invoiceItemGeneratorLogger = new InvoiceItemGeneratorLogger(invoiceId, accountId, "fixed", log);
+
final Iterator<BillingEvent> eventIt = events.iterator();
while (eventIt.hasNext()) {
final BillingEvent thisEvent = eventIt.next();
- final InvoiceItem currentFixedPriceItem = generateFixedPriceItem(invoiceId, accountId, thisEvent, targetDate, currency, internalCallContext);
+ final InvoiceItem currentFixedPriceItem = generateFixedPriceItem(invoiceId, accountId, thisEvent, targetDate, currency, invoiceItemGeneratorLogger, internalCallContext);
if (!isSameDayAndSameSubscription(prevItem, thisEvent, internalCallContext) && prevItem != null) {
proposedItems.add(prevItem);
}
@@ -151,6 +152,8 @@ public class FixedAndRecurringInvoiceItemGenerator extends InvoiceItemGenerator
if (prevItem != null) {
proposedItems.add(prevItem);
}
+
+ invoiceItemGeneratorLogger.logItems();
}
@VisibleForTesting
@@ -168,12 +171,11 @@ public class FixedAndRecurringInvoiceItemGenerator extends InvoiceItemGenerator
// Turn a set of events into a list of invoice items. Note that the dates on the invoice items will be rounded (granularity of a day)
private List<InvoiceItem> processRecurringEvent(final UUID invoiceId, final UUID accountId, final BillingEvent thisEvent, @Nullable final BillingEvent nextEvent,
final LocalDate targetDate, final Currency currency,
- final StringBuilder logStringBuilder, final BillingMode billingMode,
+ final InvoiceItemGeneratorLogger invoiceItemGeneratorLogger, final BillingMode billingMode,
final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDate,
final InternalCallContext internalCallContext) throws InvoiceApiException {
try {
-
final List<InvoiceItem> items = new ArrayList<InvoiceItem>();
// For FIXEDTERM phases we need to stop when the specified duration has been reached
@@ -224,14 +226,10 @@ public class FixedAndRecurringInvoiceItemGenerator extends InvoiceItemGenerator
}
// For debugging purposes
- logStringBuilder.append("\n")
- .append(thisEvent);
- for (final InvoiceItem item : items) {
- logStringBuilder.append("\n\t")
- .append(item);
- }
- return items;
+ invoiceItemGeneratorLogger.append(thisEvent, items);
+
+ return items;
} catch (final CatalogApiException e) {
throw new InvoiceApiException(e);
}
@@ -365,7 +363,8 @@ public class FixedAndRecurringInvoiceItemGenerator extends InvoiceItemGenerator
}
private InvoiceItem generateFixedPriceItem(final UUID invoiceId, final UUID accountId, final BillingEvent thisEvent,
- final LocalDate targetDate, final Currency currency, final InternalCallContext internalCallContext) throws InvoiceApiException {
+ final LocalDate targetDate, final Currency currency,
+ final InvoiceItemGeneratorLogger invoiceItemGeneratorLogger, final InternalCallContext internalCallContext) throws InvoiceApiException {
final LocalDate roundedStartDate = internalCallContext.toLocalDate(thisEvent.getEffectiveDate());
if (roundedStartDate.isAfter(targetDate)) {
return null;
@@ -373,10 +372,15 @@ public class FixedAndRecurringInvoiceItemGenerator extends InvoiceItemGenerator
final BigDecimal fixedPrice = thisEvent.getFixedPrice();
if (fixedPrice != null) {
- return new FixedPriceInvoiceItem(invoiceId, accountId, thisEvent.getSubscription().getBundleId(),
- thisEvent.getSubscription().getId(),
- thisEvent.getPlan().getName(), thisEvent.getPlanPhase().getName(),
- roundedStartDate, fixedPrice, currency);
+ final FixedPriceInvoiceItem fixedPriceInvoiceItem = new FixedPriceInvoiceItem(invoiceId, accountId, thisEvent.getSubscription().getBundleId(),
+ thisEvent.getSubscription().getId(),
+ thisEvent.getPlan().getName(), thisEvent.getPlanPhase().getName(),
+ roundedStartDate, fixedPrice, currency);
+
+ // For debugging purposes
+ invoiceItemGeneratorLogger.append(thisEvent, fixedPriceInvoiceItem);
+
+ return fixedPriceInvoiceItem;
} else {
return null;
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/generator/InvoiceItemGenerator.java b/invoice/src/main/java/org/killbill/billing/invoice/generator/InvoiceItemGenerator.java
index d9b3090..eb2ce88 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/generator/InvoiceItemGenerator.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/generator/InvoiceItemGenerator.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2014-2015 Groupon, Inc
- * Copyright 2014-2015 The Billing Project, LLC
+ * Copyright 2014-2016 Groupon, Inc
+ * Copyright 2014-2016 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
@@ -17,6 +17,7 @@
package org.killbill.billing.invoice.generator;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -32,6 +33,7 @@ import org.killbill.billing.invoice.api.InvoiceApiException;
import org.killbill.billing.invoice.api.InvoiceItem;
import org.killbill.billing.invoice.generator.InvoiceWithMetadata.SubscriptionFutureNotificationDates;
import org.killbill.billing.junction.BillingEventSet;
+import org.slf4j.Logger;
public abstract class InvoiceItemGenerator {
@@ -40,4 +42,60 @@ public abstract class InvoiceItemGenerator {
final Currency targetCurrency, Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDate,
final InternalCallContext context) throws InvoiceApiException;
+ public static class InvoiceItemGeneratorLogger {
+
+ private final UUID invoiceId;
+ private final UUID accountId;
+ private final String type;
+ private final Logger delegate;
+
+ private StringBuilder logStringBuilder = null;
+
+ public InvoiceItemGeneratorLogger(final UUID invoiceId, final UUID accountId, final String type, final Logger delegate) {
+ this.invoiceId = invoiceId;
+ this.accountId = accountId;
+ this.type = type;
+ this.delegate = delegate;
+ }
+
+ public void append(final Object event, final Collection<InvoiceItem> items) {
+ if (items.isEmpty()) {
+ return;
+ }
+ append(event, items.toArray(new InvoiceItem[items.size()]));
+ }
+
+ public void append(final Object event, final InvoiceItem... items) {
+ if (items.length == 0) {
+ return;
+ }
+
+ getLogStringBuilder().append("\n")
+ .append(event);
+
+ for (final InvoiceItem item : items) {
+ getLogStringBuilder().append("\n\t")
+ .append(item);
+ }
+ }
+
+ public void logItems() {
+ if (logStringBuilder != null) {
+ delegate.info(getLogStringBuilder().toString());
+ }
+ }
+
+ private StringBuilder getLogStringBuilder() {
+ if (logStringBuilder == null) {
+ logStringBuilder = new StringBuilder("Proposed ").append(type)
+ .append(" items for invoiceId='")
+ .append(invoiceId)
+ .append("', accountId='")
+ .append(accountId)
+ .append("'");
+ }
+
+ return logStringBuilder;
+ }
+ }
}
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 d94b8f9..f7b22d7 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
@@ -79,6 +79,8 @@ public class UsageInvoiceItemGenerator extends InvoiceItemGenerator {
final InternalCallContext internalCallContext) throws InvoiceApiException {
final Map<UUID, List<InvoiceItem>> perSubscriptionConsumableInArrearUsageItems = extractPerSubscriptionExistingConsumableInArrearUsageItems(eventSet.getUsages(), existingInvoices);
try {
+ // Pretty-print the generated invoice items from the junction events
+ final InvoiceItemGeneratorLogger invoiceItemGeneratorLogger = new InvoiceItemGeneratorLogger(invoiceId, account.getId(), "usage", log);
final LocalDate minBillingEventDate = getMinBillingEventDate(eventSet, internalCallContext);
@@ -118,7 +120,7 @@ public class UsageInvoiceItemGenerator extends InvoiceItemGenerator {
final SubscriptionConsumableInArrear subscriptionConsumableInArrear = new SubscriptionConsumableInArrear(account.getId(), invoiceId, curEvents, rawUsageOptimizerResult.getRawUsage(), targetDate, rawUsageOptimizerResult.getRawUsageStartDate(), internalCallContext);
final List<InvoiceItem> consumableInUsageArrearItems = perSubscriptionConsumableInArrearUsageItems.get(curSubscriptionId);
- final SubscriptionConsumableInArrearItemsAndNextNotificationDate subscriptionResult = subscriptionConsumableInArrear.computeMissingUsageInvoiceItems(consumableInUsageArrearItems != null ? consumableInUsageArrearItems : ImmutableList.<InvoiceItem>of());
+ final SubscriptionConsumableInArrearItemsAndNextNotificationDate subscriptionResult = subscriptionConsumableInArrear.computeMissingUsageInvoiceItems(consumableInUsageArrearItems != null ? consumableInUsageArrearItems : ImmutableList.<InvoiceItem>of(), invoiceItemGeneratorLogger);
final List<InvoiceItem> newInArrearUsageItems = subscriptionResult.getInvoiceItems();
items.addAll(newInArrearUsageItems);
updatePerSubscriptionNextNotificationUsageDate(curSubscriptionId, subscriptionResult.getPerUsageNotificationDates(), BillingMode.IN_ARREAR, perSubscriptionFutureNotificationDates);
@@ -131,13 +133,15 @@ public class UsageInvoiceItemGenerator extends InvoiceItemGenerator {
final SubscriptionConsumableInArrear subscriptionConsumableInArrear = new SubscriptionConsumableInArrear(account.getId(), invoiceId, curEvents, rawUsageOptimizerResult.getRawUsage(), targetDate, rawUsageOptimizerResult.getRawUsageStartDate(), internalCallContext);
final List<InvoiceItem> consumableInUsageArrearItems = perSubscriptionConsumableInArrearUsageItems.get(curSubscriptionId);
- final SubscriptionConsumableInArrearItemsAndNextNotificationDate subscriptionResult = subscriptionConsumableInArrear.computeMissingUsageInvoiceItems(consumableInUsageArrearItems != null ? consumableInUsageArrearItems : ImmutableList.<InvoiceItem>of());
+ final SubscriptionConsumableInArrearItemsAndNextNotificationDate subscriptionResult = subscriptionConsumableInArrear.computeMissingUsageInvoiceItems(consumableInUsageArrearItems != null ? consumableInUsageArrearItems : ImmutableList.<InvoiceItem>of(), invoiceItemGeneratorLogger);
final List<InvoiceItem> newInArrearUsageItems = subscriptionResult.getInvoiceItems();
items.addAll(newInArrearUsageItems);
updatePerSubscriptionNextNotificationUsageDate(curSubscriptionId, subscriptionResult.getPerUsageNotificationDates(), BillingMode.IN_ARREAR, perSubscriptionFutureNotificationDates);
}
- return items;
+ invoiceItemGeneratorLogger.logItems();
+
+ return items;
} catch (CatalogApiException e) {
throw new InvoiceApiException(e);
}
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 97cb002..dff9142 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
@@ -460,14 +460,14 @@ public class InvoiceDispatcher {
private void logInvoiceWithItems(final ImmutableAccountData account, final Invoice invoice, final LocalDate targetDate, final Set<UUID> adjustedUniqueOtherInvoiceId, final boolean isRealInvoiceWithItems) {
final StringBuilder tmp = new StringBuilder();
if (isRealInvoiceWithItems) {
- tmp.append(String.format("Generated invoiceId='%s', numberOfItems='%d', accountId='%s', targetDate='%s':\n", invoice.getId(), invoice.getNumberOfItems(), account.getId(), targetDate));
+ tmp.append(String.format("Generated invoiceId='%s', numberOfItems='%d', accountId='%s', targetDate='%s':", invoice.getId(), invoice.getNumberOfItems(), account.getId(), targetDate));
} else {
final String adjustedInvoices = JOINER_COMMA.join(adjustedUniqueOtherInvoiceId.toArray(new UUID[adjustedUniqueOtherInvoiceId.size()]));
tmp.append(String.format("Adjusting existing invoiceId='%s', numberOfItems='%d', accountId='%s', targetDate='%s':\n",
adjustedInvoices, invoice.getNumberOfItems(), account.getId(), targetDate));
}
for (final InvoiceItem item : invoice.getInvoiceItems()) {
- tmp.append(String.format("\t item = %s\n", item));
+ tmp.append(String.format("\n\t item = %s", item));
}
log.info(tmp.toString());
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableInArrear.java b/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableInArrear.java
index 3e9c5e8..785b05e 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableInArrear.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableInArrear.java
@@ -441,4 +441,14 @@ public class ContiguousIntervalConsumableInArrear {
return billingEvents.get(0).getTimeZone();
}
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("ContiguousIntervalConsumableInArrear{");
+ sb.append("transitionTimes=").append(transitionTimes);
+ sb.append(", billingEvents=").append(billingEvents);
+ sb.append(", rawSubscriptionUsage=").append(rawSubscriptionUsage);
+ sb.append(", rawUsageStartDate=").append(rawUsageStartDate);
+ sb.append('}');
+ return sb.toString();
+ }
}
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 854a91f..eebec9d 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
@@ -68,8 +68,8 @@ public class RawUsageOptimizer {
public RawUsageOptimizerResult getConsumableInArrearUsage(final LocalDate firstEventStartDate, final LocalDate targetDate, final Iterable<InvoiceItem> existingUsageItems, final Map<String, Usage> knownUsage, final InternalCallContext internalCallContext) {
final LocalDate targetStartDate = config.getMaxRawUsagePreviousPeriod(internalCallContext) > 0 ? getOptimizedRawUsageStartDate(firstEventStartDate, targetDate, existingUsageItems, knownUsage, internalCallContext) : firstEventStartDate;
- log.info("ConsumableInArrear accountRecordId='{}', rawUsageStartDate='{}', firstEventStartDate='{}'",
- internalCallContext.getAccountRecordId(), targetStartDate, firstEventStartDate);
+ log.debug("ConsumableInArrear accountRecordId='{}', rawUsageStartDate='{}', firstEventStartDate='{}'",
+ internalCallContext.getAccountRecordId(), targetStartDate, firstEventStartDate);
final List<RawUsage> rawUsageData = usageApi.getRawUsageForAccount(targetStartDate, targetDate, internalCallContext);
return new RawUsageOptimizerResult(firstEventStartDate, targetStartDate, rawUsageData);
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/usage/SubscriptionConsumableInArrear.java b/invoice/src/main/java/org/killbill/billing/invoice/usage/SubscriptionConsumableInArrear.java
index 28b6aca..4245c29 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/usage/SubscriptionConsumableInArrear.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/usage/SubscriptionConsumableInArrear.java
@@ -34,6 +34,7 @@ import org.killbill.billing.catalog.api.CatalogApiException;
import org.killbill.billing.catalog.api.Usage;
import org.killbill.billing.catalog.api.UsageType;
import org.killbill.billing.invoice.api.InvoiceItem;
+import org.killbill.billing.invoice.generator.InvoiceItemGenerator.InvoiceItemGeneratorLogger;
import org.killbill.billing.invoice.usage.ContiguousIntervalConsumableInArrear.ConsumableInArrearItemsAndNextNotificationDate;
import org.killbill.billing.junction.BillingEvent;
import org.killbill.billing.usage.RawUsage;
@@ -109,12 +110,17 @@ public class SubscriptionConsumableInArrear {
* @return
* @throws CatalogApiException
*/
- public SubscriptionConsumableInArrearItemsAndNextNotificationDate computeMissingUsageInvoiceItems(final List<InvoiceItem> existingUsage) throws CatalogApiException {
+ public SubscriptionConsumableInArrearItemsAndNextNotificationDate computeMissingUsageInvoiceItems(final List<InvoiceItem> existingUsage, final InvoiceItemGeneratorLogger invoiceItemGeneratorLogger) throws CatalogApiException {
final SubscriptionConsumableInArrearItemsAndNextNotificationDate result = new SubscriptionConsumableInArrearItemsAndNextNotificationDate();
final List<ContiguousIntervalConsumableInArrear> billingEventTransitionTimePeriods = computeInArrearUsageInterval();
for (ContiguousIntervalConsumableInArrear usageInterval : billingEventTransitionTimePeriods) {
- result.addConsumableInArrearItemsAndNextNotificationDate(usageInterval.getUsage().getName(), usageInterval.computeMissingItemsAndNextNotificationDate(existingUsage));
+ final ConsumableInArrearItemsAndNextNotificationDate newItemsAndDate = usageInterval.computeMissingItemsAndNextNotificationDate(existingUsage);
+
+ // For debugging purposes
+ invoiceItemGeneratorLogger.append(usageInterval, newItemsAndDate.getInvoiceItems());
+
+ result.addConsumableInArrearItemsAndNextNotificationDate(usageInterval.getUsage().getName(), newItemsAndDate);
}
return result;
}
diff --git a/usage/src/main/java/org/killbill/billing/usage/api/svcs/DefaultRawUsage.java b/usage/src/main/java/org/killbill/billing/usage/api/svcs/DefaultRawUsage.java
index 7ce8718..dfd8c2b 100644
--- a/usage/src/main/java/org/killbill/billing/usage/api/svcs/DefaultRawUsage.java
+++ b/usage/src/main/java/org/killbill/billing/usage/api/svcs/DefaultRawUsage.java
@@ -55,4 +55,15 @@ public class DefaultRawUsage implements RawUsage {
public Long getAmount() {
return amount;
}
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("DefaultRawUsage{");
+ sb.append("subscriptionId=").append(subscriptionId);
+ sb.append(", recordDate=").append(recordDate);
+ sb.append(", unitType='").append(unitType).append('\'');
+ sb.append(", amount=").append(amount);
+ sb.append('}');
+ return sb.toString();
+ }
}