killbill-memoizeit

Details

diff --git a/invoice/src/main/java/org/killbill/billing/invoice/api/migration/DefaultInvoiceMigrationApi.java b/invoice/src/main/java/org/killbill/billing/invoice/api/migration/DefaultInvoiceMigrationApi.java
index 159701c..a9a8a42 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/api/migration/DefaultInvoiceMigrationApi.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/api/migration/DefaultInvoiceMigrationApi.java
@@ -17,6 +17,7 @@
 package org.killbill.billing.invoice.api.migration;
 
 import java.math.BigDecimal;
+import java.util.List;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
@@ -76,7 +77,7 @@ public class DefaultInvoiceMigrationApi implements InvoiceMigrationApi {
                                                                                  MigrationPlan.MIGRATION_PLAN_NAME, MigrationPlan.MIGRATION_PLAN_PHASE_NAME, null,
                                                                                  targetDate, null, balance, null, currency, null);
         dao.createInvoice(migrationInvoice, ImmutableList.<InvoiceItemModelDao>of(migrationInvoiceItem),
-                          ImmutableList.<InvoicePaymentModelDao>of(), true, ImmutableMap.<UUID, DateTime>of(), internalCallContextFactory.createInternalCallContext(accountId, context));
+                          ImmutableList.<InvoicePaymentModelDao>of(), true, ImmutableMap.<UUID, List<DateTime>>of(), internalCallContextFactory.createInternalCallContext(accountId, context));
 
         return migrationInvoice.getId();
     }
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 39ff308..782a04c 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
@@ -201,7 +201,7 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
 
     @Override
     public void createInvoice(final InvoiceModelDao invoice, final List<InvoiceItemModelDao> invoiceItems,
-                              final List<InvoicePaymentModelDao> invoicePayments, final boolean isRealInvoice, final Map<UUID, DateTime> callbackDateTimePerSubscriptions,
+                              final List<InvoicePaymentModelDao> invoicePayments, final boolean isRealInvoice, final Map<UUID, List<DateTime>> callbackDateTimePerSubscriptions,
                               final InternalCallContext context) {
         transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
             @Override
@@ -760,10 +760,12 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
     }
 
     private void notifyOfFutureBillingEvents(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory, final UUID accountId,
-                                             final Map<UUID, DateTime> callbackDateTimePerSubscriptions, final UUID userToken) {
+                                             final Map<UUID, List<DateTime>> callbackDateTimePerSubscriptions, final UUID userToken) {
         for (final UUID subscriptionId : callbackDateTimePerSubscriptions.keySet()) {
-            final DateTime callbackDateTimeUTC = callbackDateTimePerSubscriptions.get(subscriptionId);
-            nextBillingDatePoster.insertNextBillingNotificationFromTransaction(entitySqlDaoWrapperFactory, accountId, subscriptionId, callbackDateTimeUTC, userToken);
+            final List<DateTime> callbackDateTimeUTC = callbackDateTimePerSubscriptions.get(subscriptionId);
+            for (DateTime cur : callbackDateTimeUTC) {
+                nextBillingDatePoster.insertNextBillingNotificationFromTransaction(entitySqlDaoWrapperFactory, accountId, subscriptionId, cur, userToken);
+            }
         }
     }
 
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 8b8cd3f..5adb05e 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
@@ -37,7 +37,7 @@ import org.killbill.billing.util.entity.dao.EntityDao;
 public interface InvoiceDao extends EntityDao<InvoiceModelDao, Invoice, InvoiceApiException> {
 
     void createInvoice(InvoiceModelDao invoice, List<InvoiceItemModelDao> invoiceItems,
-                       List<InvoicePaymentModelDao> invoicePayments, boolean isRealInvoice, final Map<UUID, DateTime> callbackDateTimePerSubscriptions, InternalCallContext context);
+                       List<InvoicePaymentModelDao> invoicePayments, boolean isRealInvoice, final Map<UUID, List<DateTime>> callbackDateTimePerSubscriptions, InternalCallContext context);
 
     InvoiceModelDao getByNumber(Integer number, InternalTenantContext context) throws InvoiceApiException;
 
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 1dba77c..24e9132 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
@@ -30,6 +30,10 @@ import javax.annotation.Nullable;
 
 import org.joda.time.DateTime;
 import org.joda.time.LocalDate;
+import org.killbill.billing.catalog.api.BillingMode;
+import org.killbill.billing.catalog.api.Usage;
+import org.killbill.billing.invoice.usage.UsageUtils;
+import org.killbill.billing.junction.BillingEvent;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -82,6 +86,7 @@ import com.google.common.base.Function;
 import com.google.common.base.Joiner;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
 import com.google.inject.Inject;
 
 public class InvoiceDispatcher {
@@ -239,7 +244,7 @@ public class InvoiceDispatcher {
                                                                                                                                                          }
                                                                                                                                                      }));
 
-                    final Map<UUID, DateTime> callbackDateTimePerSubscriptions = createNextFutureNotificationDate(invoiceItemModelDaos, dateAndTimeZoneContext);
+                    final Map<UUID, List<DateTime>> callbackDateTimePerSubscriptions = createNextFutureNotificationDate(invoiceItemModelDaos, UsageUtils.getKnownUsages(billingEvents, null), dateAndTimeZoneContext);
                     invoiceDao.createInvoice(invoiceModelDao, invoiceItemModelDaos, invoicePaymentModelDaos, isRealInvoiceWithItems, callbackDateTimePerSubscriptions, context);
 
                     final List<InvoiceItem> fixedPriceInvoiceItems = invoice.getInvoiceItems(FixedPriceInvoiceItem.class);
@@ -283,23 +288,62 @@ public class InvoiceDispatcher {
         return context.toTenantContext(nonEntityDao.retrieveIdFromObject(context.getTenantRecordId(), ObjectType.TENANT));
     }
 
+
     @VisibleForTesting
-    Map<UUID, DateTime> createNextFutureNotificationDate(final List<InvoiceItemModelDao> invoiceItems, final DateAndTimeZoneContext dateAndTimeZoneContext) {
-        final Map<UUID, DateTime> result = new HashMap<UUID, DateTime>();
+    Map<UUID, List<DateTime>> createNextFutureNotificationDate(final List<InvoiceItemModelDao> invoiceItems, final Map<String, Usage> knownUsages, final DateAndTimeZoneContext dateAndTimeZoneContext) {
+
+        final Map<UUID, List<DateTime>> result = new HashMap<UUID, List<DateTime>>();
+
+        final Map<String, LocalDate> perSubscriptionUsage = new HashMap<String, LocalDate>();
 
         // For each subscription that has a positive (amount) recurring item, create the date
         // at which we should be called back for next invoice.
         //
         for (final InvoiceItemModelDao item : invoiceItems) {
 
-            if (item.getType() == InvoiceItemType.RECURRING) {
-                if ((item.getEndDate() != null) &&
-                    (item.getAmount() == null ||
-                     item.getAmount().compareTo(BigDecimal.ZERO) >= 0)) {
-                    result.put(item.getSubscriptionId(), dateAndTimeZoneContext.computeUTCDateTimeFromLocalDate(item.getEndDate()));
-                }
+            List<DateTime> perSubscriptionCallback = result.get(item.getSubscriptionId());
+            if (perSubscriptionCallback == null && (item.getType() == InvoiceItemType.RECURRING || item.getType() == InvoiceItemType.USAGE)) {
+                perSubscriptionCallback = new ArrayList<DateTime>();
+                result.put(item.getSubscriptionId(), perSubscriptionCallback);
+            }
+
+            switch(item.getType()) {
+                case RECURRING:
+                    if ((item.getEndDate() != null) &&
+                        (item.getAmount() == null ||
+                         item.getAmount().compareTo(BigDecimal.ZERO) >= 0)) {
+                        perSubscriptionCallback.add(dateAndTimeZoneContext.computeUTCDateTimeFromLocalDate(item.getEndDate()));
+                    }
+                    break;
+
+                case USAGE:
+                    final Usage usage = knownUsages.get(item.getUsageName());
+                    final String key = item.getSubscriptionId().toString() + ":" + usage.getName();
+                    final LocalDate perSubscriptionUsageRecurringDate  = perSubscriptionUsage.get(key);
+                    if (perSubscriptionUsageRecurringDate == null || perSubscriptionUsageRecurringDate.compareTo(item.getEndDate()) < 0) {
+                        perSubscriptionUsage.put(key, item.getEndDate());
+                    }
+                    break;
+
+                default:
+                    // Ignore
             }
         }
+
+        for (final String key : perSubscriptionUsage.keySet()) {
+            final String [] parts = key.split(":");
+            final UUID subscriptionId = UUID.fromString(parts[0]);
+
+            final List<DateTime> perSubscriptionCallback = result.get(subscriptionId);
+            final String usageName = parts[1];
+            final Usage usage = knownUsages.get(usageName);
+
+            final LocalDate endDate =  perSubscriptionUsage.get(key);
+            // STEPH_USAGE WE should double check this is indeed the right date to be called back for that subscription/usage section.
+            final LocalDate nextCallbackUsageDate = (usage.getBillingMode() == BillingMode.IN_ARREAR) ? endDate.plusMonths(usage.getBillingPeriod().getNumberOfMonths()) : endDate;
+            perSubscriptionCallback.add(dateAndTimeZoneContext.computeUTCDateTimeFromLocalDate(nextCallbackUsageDate));
+        }
+
         return result;
     }
 
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousInArrearUsageInterval.java b/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousInArrearUsageInterval.java
index 59d4878..9df894e 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousInArrearUsageInterval.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousInArrearUsageInterval.java
@@ -48,9 +48,8 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
-import static org.killbill.billing.invoice.usage.SubscriptionConsumableInArrear.getTieredBlocks;
-import static org.killbill.billing.invoice.usage.SubscriptionConsumableInArrear.getUnitTypes;
-import static org.killbill.billing.invoice.usage.SubscriptionConsumableInArrear.localDateToEndOfDayInAccountTimezone;
+import static org.killbill.billing.invoice.usage.UsageUtils.getConsumableInArrearTieredBlocks;
+import static org.killbill.billing.invoice.usage.UsageUtils.getConsumableInArrearUnitTypes;
 
 /**
  * There is one such class per subscriptionId, matching a given in arrear/consumable usage section and
@@ -71,7 +70,7 @@ public class ContiguousInArrearUsageInterval {
     public ContiguousInArrearUsageInterval(final Usage usage, final UUID invoiceId, final UsageUserApi usageApi, final LocalDate targetDate, final TenantContext context) {
         this.usage = usage;
         this.invoiceId = invoiceId;
-        this.unitTypes = getUnitTypes(usage);
+        this.unitTypes = getConsumableInArrearUnitTypes(usage);
         this.usageApi = usageApi;
         this.targetDate = targetDate;
         this.context = context;
@@ -164,7 +163,7 @@ public class ContiguousInArrearUsageInterval {
 
         BigDecimal result = BigDecimal.ZERO;
 
-        final List<TieredBlock> tieredBlocks = getTieredBlocks(usage, unitType);
+        final List<TieredBlock> tieredBlocks = getConsumableInArrearTieredBlocks(usage, unitType);
         int remainingUnits = nbUnits.intValue();
         for (TieredBlock tieredBlock : tieredBlocks) {
 
@@ -328,4 +327,10 @@ public class ContiguousInArrearUsageInterval {
     public DateTimeZone getAccountTimeZone() {
         return billingEvents.get(0).getTimeZone();
     }
+
+    static DateTime localDateToEndOfDayInAccountTimezone(final LocalDate input, final DateTimeZone accountTimeZone) {
+        final DateTime dateTimeInAccountTimeZone = new DateTime(input.getYear(), input.getMonthOfYear(), input.getDayOfMonth(), 23, 59, 59, accountTimeZone);
+        return new DateTime(dateTimeInAccountTimeZone, DateTimeZone.UTC);
+    }
+
 }
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 6736857..1c62249 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
@@ -132,36 +132,4 @@ public class SubscriptionConsumableInArrear {
         }
         return result;
     }
-
-    static List<TieredBlock> getTieredBlocks(final Usage usage, final String unitType) {
-
-        Preconditions.checkArgument(usage.getTiers().length > 0);
-
-        final List<TieredBlock> result = Lists.newLinkedList();
-        for (Tier tier : usage.getTiers()) {
-            for (TieredBlock tierBlock : tier.getTieredBlocks()) {
-                if (tierBlock.getUnit().getName().equals(unitType)) {
-                    result.add(tierBlock);
-                }
-            }
-        }
-        return result;
-    }
-
-    static DateTime localDateToEndOfDayInAccountTimezone(final LocalDate input, final DateTimeZone accountTimeZone) {
-        final DateTime dateTimeInAccountTimeZone = new DateTime(input.getYear(), input.getMonthOfYear(), input.getDayOfMonth(), 23, 59, 59, accountTimeZone);
-        return new DateTime(dateTimeInAccountTimeZone, DateTimeZone.UTC);
-    }
-
-    static Set<String> getUnitTypes(final Usage usage) {
-        Preconditions.checkArgument(usage.getTiers().length > 0);
-
-        final Set<String> result = new HashSet<String>();
-        for (Tier tier : usage.getTiers()) {
-            for (TieredBlock tierBlock : tier.getTieredBlocks()) {
-                result.add(tierBlock.getUnit().getName());
-            }
-        }
-        return result;
-    }
 }
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/usage/UsageUtils.java b/invoice/src/main/java/org/killbill/billing/invoice/usage/UsageUtils.java
new file mode 100644
index 0000000..f60510e
--- /dev/null
+++ b/invoice/src/main/java/org/killbill/billing/invoice/usage/UsageUtils.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2014 The Billing Project, Inc.
+ *
+ * Ning 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.usage;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
+import org.killbill.billing.catalog.api.BillingMode;
+import org.killbill.billing.catalog.api.Tier;
+import org.killbill.billing.catalog.api.TieredBlock;
+import org.killbill.billing.catalog.api.Usage;
+import org.killbill.billing.catalog.api.UsageType;
+import org.killbill.billing.junction.BillingEvent;
+import org.killbill.billing.junction.BillingEventSet;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+public class UsageUtils {
+
+    public static Map<String, Usage> getKnownUsages(final BillingEventSet billingEvents, @Nullable final Predicate filter) {
+        final Iterable<Usage> usages = Iterables.concat(Iterables.transform(billingEvents, new Function<BillingEvent, List<Usage>>() {
+            @Override
+            public List<Usage> apply(final BillingEvent input) {
+                return input.getUsages();
+            }
+        }));
+
+        final Iterable<Usage> filteredUsages = (filter != null) ? Iterables.filter(usages, filter) : usages;
+
+        final Map<String, Usage> result = (filteredUsages.iterator().hasNext()) ? new HashMap<String, Usage>() : Collections.<String, Usage>emptyMap();
+        while (filteredUsages.iterator().hasNext()) {
+            final Usage next = filteredUsages.iterator().next();
+            result.put(next.getName(), next);
+        }
+        return result;
+    }
+
+    public static List<TieredBlock> getConsumableInArrearTieredBlocks(final Usage usage, final String unitType) {
+
+        Preconditions.checkArgument(usage.getBillingMode() == BillingMode.IN_ARREAR && usage.getUsageType() == UsageType.CONSUMABLE);
+        Preconditions.checkArgument(usage.getTiers().length > 0);
+
+        final List<TieredBlock> result = Lists.newLinkedList();
+        for (Tier tier : usage.getTiers()) {
+            for (TieredBlock tierBlock : tier.getTieredBlocks()) {
+                if (tierBlock.getUnit().getName().equals(unitType)) {
+                    result.add(tierBlock);
+                }
+            }
+        }
+        return result;
+    }
+
+    public static Set<String> getConsumableInArrearUnitTypes(final Usage usage) {
+
+        Preconditions.checkArgument(usage.getBillingMode() == BillingMode.IN_ARREAR && usage.getUsageType() == UsageType.CONSUMABLE);
+        Preconditions.checkArgument(usage.getTiers().length > 0);
+
+        final Set<String> result = new HashSet<String>();
+        for (Tier tier : usage.getTiers()) {
+            for (TieredBlock tierBlock : tier.getTieredBlocks()) {
+                result.add(tierBlock.getUnit().getName());
+            }
+        }
+        return result;
+    }
+
+}
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 879fe02..6edc2b3 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
@@ -60,7 +60,7 @@ public class MockInvoiceDao extends MockEntityDaoBase<InvoiceModelDao, Invoice, 
 
     @Override
     public void createInvoice(final InvoiceModelDao invoice, final List<InvoiceItemModelDao> invoiceItems,
-                              final List<InvoicePaymentModelDao> invoicePayments, final boolean isRealInvoice, final Map<UUID, DateTime> callbackDateTimePerSubscriptions, final InternalCallContext context) {
+                              final List<InvoicePaymentModelDao> invoicePayments, final boolean isRealInvoice, final Map<UUID, List<DateTime>> callbackDateTimePerSubscriptions, final InternalCallContext context) {
         synchronized (monitor) {
             invoices.put(invoice.getId(), invoice);
             for (final InvoiceItemModelDao invoiceItemModelDao : invoiceItems) {
@@ -87,6 +87,7 @@ public class MockInvoiceDao extends MockEntityDaoBase<InvoiceModelDao, Invoice, 
         }
     }
 
+
     @Override
     public InvoiceModelDao getByNumber(final Integer number, final InternalTenantContext context) {
         synchronized (monitor) {
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceDispatcher.java b/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceDispatcher.java
index cf263e3..a306cab 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceDispatcher.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceDispatcher.java
@@ -206,15 +206,16 @@ public class TestInvoiceDispatcher extends InvoiceTestSuiteWithEmbeddedDB {
                                                                    nonEntityDao, invoiceNotifier, locker, busService.getBus(),
                                                                    clock);
 
-        final Map<UUID, DateTime> result = dispatcher.createNextFutureNotificationDate(Collections.singletonList(item), dateAndTimeZoneContext);
+        final Map<UUID, List<DateTime>> result = dispatcher.createNextFutureNotificationDate(Collections.singletonList(item), null, dateAndTimeZoneContext);
 
         Assert.assertEquals(result.size(), 1);
 
-        final DateTime receivedDate = result.get(item.getSubscriptionId());
+        final List<DateTime> receivedDates = result.get(item.getSubscriptionId());
+        Assert.assertEquals(receivedDates.size(), 1);
 
-        final LocalDate receivedTargetDate = new LocalDate(receivedDate, DateTimeZone.forID("Pacific/Pitcairn"));
+        final LocalDate receivedTargetDate = new LocalDate(receivedDates.get(0), DateTimeZone.forID("Pacific/Pitcairn"));
         Assert.assertEquals(receivedTargetDate, endDate);
 
-        Assert.assertTrue(receivedDate.compareTo(new DateTime(2012, 11, 27, 1, 12, 23, DateTimeZone.UTC)) <= 0);
+        Assert.assertTrue(receivedDates.get(0).compareTo(new DateTime(2012, 11, 27, 1, 12, 23, DateTimeZone.UTC)) <= 0);
     }
 }
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceHelper.java b/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceHelper.java
index 3f51e54..91a4385 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceHelper.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceHelper.java
@@ -273,7 +273,7 @@ public class TestInvoiceHelper {
                                                                                                                                          }));
 
         // The test does not use the invoice callback notifier hence the empty map
-        invoiceDao.createInvoice(invoiceModelDao, invoiceItemModelDaos, invoicePaymentModelDaos, isRealInvoiceWithItems, ImmutableMap.<UUID, DateTime>of(), internalCallContext);
+        invoiceDao.createInvoice(invoiceModelDao, invoiceItemModelDaos, invoicePaymentModelDaos, isRealInvoiceWithItems, ImmutableMap.<UUID, List<DateTime>>of(), internalCallContext);
     }
 
     public void createPayment(final InvoicePayment invoicePayment, final InternalCallContext internalCallContext) {
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/tests/InvoiceTestUtils.java b/invoice/src/test/java/org/killbill/billing/invoice/tests/InvoiceTestUtils.java
index b21e3e9..811dacc 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/tests/InvoiceTestUtils.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/tests/InvoiceTestUtils.java
@@ -87,7 +87,7 @@ public class InvoiceTestUtils {
         }
         Mockito.when(invoice.getInvoiceItems()).thenReturn(invoiceItems);
 
-        invoiceDao.createInvoice(new InvoiceModelDao(invoice), invoiceModelItems, ImmutableList.<InvoicePaymentModelDao>of(), true, ImmutableMap.<UUID, DateTime>of(), internalCallContext);
+        invoiceDao.createInvoice(new InvoiceModelDao(invoice), invoiceModelItems, ImmutableList.<InvoicePaymentModelDao>of(), true, ImmutableMap.<UUID, List<DateTime>>of(), internalCallContext);
 
         return invoice;
     }
diff --git a/util/src/main/java/org/killbill/billing/util/timezone/DateAndTimeZoneContext.java b/util/src/main/java/org/killbill/billing/util/timezone/DateAndTimeZoneContext.java
index 872f0e5..54fec5d 100644
--- a/util/src/main/java/org/killbill/billing/util/timezone/DateAndTimeZoneContext.java
+++ b/util/src/main/java/org/killbill/billing/util/timezone/DateAndTimeZoneContext.java
@@ -59,7 +59,7 @@ public final class DateAndTimeZoneContext {
         // Since we create the targetDate for next invoice using the date from the notificationQ, we need to make sure
         // that this datetime once transformed into a LocalDate points to the correct day.
         //
-        // All we need to do is figure is the transformation from DateTime (point in time) to LocalDate (date in account time zone)
+        // All we need to do is figure if the transformation from DateTime (point in time) to LocalDate (date in account time zone)
         // changed the day; if so, when we recompute a UTC date from LocalDate (date in account time zone), we can simply chose a reference
         // time and apply the offset backward to end up on the right day
         //