killbill-memoizeit
Changes
invoice/src/main/java/org/killbill/billing/invoice/generator/FixedAndRecurringInvoiceItemGenerator.java 27(+21 -6)
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 259c570..0f22e05 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
@@ -19,6 +19,7 @@ package org.killbill.billing.invoice.generator;
import java.math.BigDecimal;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -399,25 +400,39 @@ public class FixedAndRecurringInvoiceItemGenerator extends InvoiceItemGenerator
// Trigger an exception if we create too many subscriptions for a subscription on a given day
private void safetyBound(final Iterable<InvoiceItem> resultingItems, final Multimap<UUID, LocalDate> createdItemsPerDayPerSubscription, final InternalTenantContext internalCallContext) throws InvoiceApiException {
+ if (config.getMaxDailyNumberOfItemsSafetyBound(internalCallContext) == -1) {
+ // Safety bound disabled
+ return;
+ }
+
for (final InvoiceItem invoiceItem : resultingItems) {
if (invoiceItem.getSubscriptionId() != null) {
- trackInvoiceItemCreatedDay(invoiceItem, createdItemsPerDayPerSubscription, internalCallContext);
+ final LocalDate resultingItemCreationDay = trackInvoiceItemCreatedDay(invoiceItem, createdItemsPerDayPerSubscription, internalCallContext);
+
+ final Collection<LocalDate> creationDaysForSubscription = createdItemsPerDayPerSubscription.get(invoiceItem.getSubscriptionId());
+ int i = 0;
+ for (final LocalDate creationDayForSubscription : creationDaysForSubscription) {
+ if (creationDayForSubscription.compareTo(resultingItemCreationDay) == 0) {
+ i++;
+ if (i > config.getMaxDailyNumberOfItemsSafetyBound(internalCallContext)) {
+ // Proposed items have already been logged
+ throw new InvoiceApiException(ErrorCode.UNEXPECTED_ERROR, String.format("SAFETY BOUND TRIGGERED subscriptionId='%s', resultingItem=%s", invoiceItem.getSubscriptionId(), invoiceItem));
+ }
- if (createdItemsPerDayPerSubscription.get(invoiceItem.getSubscriptionId()).size() > config.getMaxDailyNumberOfItemsSafetyBound(internalCallContext)) {
- // Proposed items have already been logged
- throw new InvoiceApiException(ErrorCode.UNEXPECTED_ERROR, String.format("SAFETY BOUND TRIGGERED subscriptionId='%s', resultingItem=%s", invoiceItem.getSubscriptionId(), invoiceItem));
+ }
}
}
}
}
- private void trackInvoiceItemCreatedDay(final InvoiceItem invoiceItem, final Multimap<UUID, LocalDate> createdItemsPerDayPerSubscription, final InternalTenantContext internalCallContext) {
+ private LocalDate trackInvoiceItemCreatedDay(final InvoiceItem invoiceItem, final Multimap<UUID, LocalDate> createdItemsPerDayPerSubscription, final InternalTenantContext internalCallContext) {
final UUID subscriptionId = invoiceItem.getSubscriptionId();
if (subscriptionId == null) {
- return;
+ return null;
}
final LocalDate createdDay = internalCallContext.toLocalDate(invoiceItem.getCreatedDate());
createdItemsPerDayPerSubscription.put(subscriptionId, createdDay);
+ return createdDay;
}
}
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/generator/TestFixedAndRecurringInvoiceItemGenerator.java b/invoice/src/test/java/org/killbill/billing/invoice/generator/TestFixedAndRecurringInvoiceItemGenerator.java
index ca56b1f..5fbfc79 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/generator/TestFixedAndRecurringInvoiceItemGenerator.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/generator/TestFixedAndRecurringInvoiceItemGenerator.java
@@ -315,7 +315,35 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
for (int i = 0; i < threshold; i++) {
final Invoice invoice = new DefaultInvoice(account.getId(), clock.getUTCToday(), startDate.plusMonths(i), account.getCurrency());
invoice.addInvoiceItem(new RecurringInvoiceItem(UUID.randomUUID(),
- clock.getUTCNow(),
+ startDate.plusMonths(i).toDateTimeAtStartOfDay(), // Different days - should not trigger the safety bounds
+ invoice.getId(),
+ account.getId(),
+ subscription.getBundleId(),
+ subscription.getId(),
+ event.getPlan().getName(),
+ event.getPlanPhase().getName(),
+ startDate.plusMonths(i),
+ startDate.plusMonths(1 + i),
+ amount,
+ amount,
+ account.getCurrency()));
+ existingInvoices.add(invoice);
+ }
+
+ assertEquals(fixedAndRecurringInvoiceItemGenerator.generateItems(account,
+ UUID.randomUUID(),
+ events,
+ existingInvoices,
+ startDate.plusMonths(threshold),
+ account.getCurrency(),
+ new HashMap<UUID, SubscriptionFutureNotificationDates>(),
+ internalCallContext).size(), 1);
+
+ // Simulate a big catch-up on that day
+ for (int i = threshold; i < 2 * threshold; i++) {
+ final Invoice invoice = new DefaultInvoice(account.getId(), clock.getUTCToday(), startDate.plusMonths(i), account.getCurrency());
+ invoice.addInvoiceItem(new RecurringInvoiceItem(UUID.randomUUID(),
+ clock.getUTCNow(), // Same day
invoice.getId(),
account.getId(),
subscription.getBundleId(),
@@ -335,7 +363,7 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
UUID.randomUUID(),
events,
existingInvoices,
- startDate.plusMonths(threshold),
+ startDate.plusMonths(2 * threshold),
account.getCurrency(),
new HashMap<UUID, SubscriptionFutureNotificationDates>(),
internalCallContext);
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/InvoiceTestSuiteWithEmbeddedDB.java b/invoice/src/test/java/org/killbill/billing/invoice/InvoiceTestSuiteWithEmbeddedDB.java
index 2f6bf60..487fd07 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/InvoiceTestSuiteWithEmbeddedDB.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/InvoiceTestSuiteWithEmbeddedDB.java
@@ -42,6 +42,7 @@ import org.killbill.billing.util.config.definition.InvoiceConfig;
import org.killbill.billing.util.dao.NonEntityDao;
import org.killbill.bus.api.PersistentBus;
import org.killbill.clock.Clock;
+import org.killbill.clock.ClockMock;
import org.killbill.commons.locker.GlobalLocker;
import org.killbill.notificationq.api.NotificationQueueService;
import org.slf4j.Logger;
@@ -91,7 +92,7 @@ public abstract class InvoiceTestSuiteWithEmbeddedDB extends GuicyKillbillTestSu
@Inject
protected GlobalLocker locker;
@Inject
- protected Clock clock;
+ protected ClockMock clock;
@Inject
protected InternalCallContextFactory internalCallContextFactory;
@Inject
@@ -127,6 +128,7 @@ public abstract class InvoiceTestSuiteWithEmbeddedDB extends GuicyKillbillTestSu
controllerDispatcher.clearAll();
bus.start();
restartInvoiceService(invoiceService);
+ clock.resetDeltaFromReality();
}
private void restartInvoiceService(final InvoiceService invoiceService) throws Exception {