killbill-aplcache

Details

diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultInternationalPrice.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultInternationalPrice.java
index cb3bb49..ed425c7 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultInternationalPrice.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultInternationalPrice.java
@@ -49,6 +49,8 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
     }
 
 
+
+
     /* (non-Javadoc)
       * @see org.killbill.billing.catalog.IInternationalPrice#getPrice(org.killbill.billing.catalog.api.Currency)
       */
@@ -62,7 +64,7 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
         throw new CatalogApiException(ErrorCode.CAT_NO_PRICE_FOR_CURRENCY, currency);
     }
 
-    protected DefaultInternationalPrice setPrices(final DefaultPrice[] prices) {
+    public DefaultInternationalPrice setPrices(final DefaultPrice[] prices) {
         this.prices = prices;
         return this;
     }
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPrice.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPrice.java
index bb3f066..cc5374c 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPrice.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPrice.java
@@ -64,12 +64,12 @@ public class DefaultPrice extends ValidatingConfig<StandaloneCatalog> implements
         return value;
     }
 
-    protected DefaultPrice setCurrency(final Currency currency) {
+    public DefaultPrice setCurrency(final Currency currency) {
         this.currency = currency;
         return this;
     }
 
-    protected DefaultPrice setValue(final BigDecimal value) {
+    public DefaultPrice setValue(final BigDecimal value) {
         this.value = value;
         return this;
     }
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultUnit.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultUnit.java
index c383024..4616e05 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultUnit.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultUnit.java
@@ -45,4 +45,8 @@ public class DefaultUnit extends ValidatingConfig<StandaloneCatalog> implements 
         return errors;
     }
 
+    public DefaultUnit setName(final String name) {
+        this.name = name;
+        return this;
+    }
 }
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 1c62249..2390514 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
@@ -18,33 +18,25 @@ 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 java.util.UUID;
 
-import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
 import org.joda.time.LocalDate;
 import org.killbill.billing.catalog.api.BillingMode;
 import org.killbill.billing.catalog.api.CatalogApiException;
-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.invoice.api.InvoiceItem;
-import org.killbill.billing.invoice.model.UsageInvoiceItem;
 import org.killbill.billing.junction.BillingEvent;
 import org.killbill.billing.usage.api.UsageUserApi;
 import org.killbill.billing.util.callcontext.TenantContext;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 
 /**
  * There is one such class created for each subscriptionId referenced in the billingEvents.
- *
  */
 public class SubscriptionConsumableInArrear {
 
@@ -72,19 +64,18 @@ public class SubscriptionConsumableInArrear {
     public List<InvoiceItem> computeMissingUsageInvoiceItems(final List<InvoiceItem> existingUsage) throws CatalogApiException {
 
         final List<InvoiceItem> result = Lists.newLinkedList();
-        final List<ContiguousInArrearUsageInterval> billingEventTransitionTimePeriods = computeInArrearUsageInterval();
-        for (ContiguousInArrearUsageInterval usageInterval : billingEventTransitionTimePeriods) {
+        final List<ContiguousIntervalConsumableInArrear> billingEventTransitionTimePeriods = computeInArrearUsageInterval();
+        for (ContiguousIntervalConsumableInArrear usageInterval : billingEventTransitionTimePeriods) {
             result.addAll(usageInterval.computeMissingItems(existingUsage));
         }
         return result;
     }
 
-    List<ContiguousInArrearUsageInterval> computeInArrearUsageInterval() {
-
-        final List<ContiguousInArrearUsageInterval> usageIntervals = Lists.newLinkedList();
+    List<ContiguousIntervalConsumableInArrear> computeInArrearUsageInterval() {
 
+        final List<ContiguousIntervalConsumableInArrear> usageIntervals = Lists.newLinkedList();
 
-        final Map<String, ContiguousInArrearUsageInterval> inFlightInArrearUsageIntervals = new HashMap<String, ContiguousInArrearUsageInterval>();
+        final Map<String, ContiguousIntervalConsumableInArrear> inFlightInArrearUsageIntervals = new HashMap<String, ContiguousIntervalConsumableInArrear>();
         for (BillingEvent event : subscriptionBillingEvents) {
 
             // All inflight usage interval are candidates to be closed unless we see that current billing event referencing the same usage section.
@@ -95,9 +86,9 @@ public class SubscriptionConsumableInArrear {
             for (Usage usage : usages) {
 
                 // Add inflight usage interval if non existent
-                ContiguousInArrearUsageInterval existingInterval = inFlightInArrearUsageIntervals.get(usage.getName());
+                ContiguousIntervalConsumableInArrear existingInterval = inFlightInArrearUsageIntervals.get(usage.getName());
                 if (existingInterval == null) {
-                    existingInterval = new ContiguousInArrearUsageInterval(usage, invoiceId, usageApi, targetDate, context);
+                    existingInterval = new ContiguousIntervalConsumableInArrear(usage, invoiceId, usageApi, targetDate, context);
                     inFlightInArrearUsageIntervals.put(usage.getName(), existingInterval);
                 }
                 // Add billing event for that usage interval
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/InvoiceTestSuiteNoDB.java b/invoice/src/test/java/org/killbill/billing/invoice/InvoiceTestSuiteNoDB.java
index c7b34cf..dc72ae4 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/InvoiceTestSuiteNoDB.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/InvoiceTestSuiteNoDB.java
@@ -32,6 +32,7 @@ import org.killbill.billing.invoice.generator.InvoiceGenerator;
 import org.killbill.billing.invoice.glue.TestInvoiceModuleNoDB;
 import org.killbill.billing.junction.BillingInternalApi;
 import org.killbill.billing.subscription.api.SubscriptionBaseInternalApi;
+import org.killbill.billing.usage.api.UsageUserApi;
 import org.killbill.billing.util.KillbillConfigSource;
 import org.killbill.billing.util.api.TagUserApi;
 import org.killbill.billing.util.cache.CacheControllerDispatcher;
@@ -90,6 +91,8 @@ public abstract class InvoiceTestSuiteNoDB extends GuicyKillbillTestSuiteNoDB {
     protected TestInvoiceHelper invoiceUtil;
     @Inject
     protected CurrencyConversionApi currencyConversionApi;
+    @Inject
+    protected UsageUserApi usageUserApi;
 
     @Override
     protected KillbillConfigSource getConfigSource() throws IOException, URISyntaxException {
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
new file mode 100644
index 0000000..a20705b
--- /dev/null
+++ b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalConsumableInArrear.java
@@ -0,0 +1,288 @@
+/*
+ * 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.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.joda.time.LocalDate;
+import org.killbill.billing.account.api.Account;
+import org.killbill.billing.catalog.DefaultInternationalPrice;
+import org.killbill.billing.catalog.DefaultPrice;
+import org.killbill.billing.catalog.DefaultTier;
+import org.killbill.billing.catalog.DefaultTieredBlock;
+import org.killbill.billing.catalog.DefaultUnit;
+import org.killbill.billing.catalog.DefaultUsage;
+import org.killbill.billing.catalog.api.BillingMode;
+import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.CatalogApiException;
+import org.killbill.billing.catalog.api.Currency;
+import org.killbill.billing.catalog.api.Plan;
+import org.killbill.billing.catalog.api.PlanPhase;
+import org.killbill.billing.catalog.api.UsageType;
+import org.killbill.billing.invoice.InvoiceTestSuiteNoDB;
+import org.killbill.billing.invoice.api.InvoiceItem;
+import org.killbill.billing.invoice.model.FixedPriceInvoiceItem;
+import org.killbill.billing.invoice.model.UsageInvoiceItem;
+import org.killbill.billing.junction.BillingEvent;
+import org.killbill.billing.subscription.api.SubscriptionBase;
+import org.killbill.billing.usage.api.RolledUpUsage;
+import org.killbill.billing.usage.api.UsageUserApi;
+import org.killbill.billing.usage.api.user.DefaultRolledUpUsage;
+import org.killbill.billing.util.callcontext.TenantContext;
+import org.mockito.Mockito;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.beust.jcommander.internal.Lists;
+import com.google.common.collect.ImmutableList;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public class TestContiguousIntervalConsumableInArrear extends InvoiceTestSuiteNoDB {
+
+    private int BCD;
+    private UUID accountId;
+    private UUID bundleId;
+    private UUID subscriptionId;
+    private UUID invoiceId;
+    private String planName;
+    private String phaseName;
+    private Currency currency;
+    private String usageName;
+
+    private UsageUserApi mockUsageUserApi;
+
+    @BeforeClass(groups = "fast")
+    protected void beforeClass() throws Exception {
+        super.beforeClass();
+        BCD = 15;
+        usageName = "foo";
+        accountId = UUID.randomUUID();
+        bundleId = UUID.randomUUID();
+        subscriptionId = UUID.randomUUID();
+        invoiceId = UUID.randomUUID();
+        planName = "planName";
+        phaseName = "phaseName";
+        currency = Currency.BTC;
+    }
+
+    @BeforeMethod(groups = "fast")
+    public void beforeMethod() {
+        super.beforeMethod();
+        // Default invoice test binding;
+        this.mockUsageUserApi = usageUserApi;
+    }
+
+    @Test(groups = "fast")
+    public void testComputeToBeBilledUsage() {
+
+        final LocalDate startDate = new LocalDate(2014, 03, 20);
+        final LocalDate endDate = new LocalDate(2014, 04, 20);
+
+        final DefaultTieredBlock block = createDefaultTieredBlock("unit", 100, 1000, BigDecimal.ONE);
+        final DefaultTier tier = createDefaultTier(block);
+        final DefaultUsage usage = createDefaultUsage(usageName, tier);
+
+        final LocalDate targetDate = startDate.plusDays(1);
+        final ContiguousIntervalConsumableInArrear intervalConsumableInArrear = createContiguousIntervalConsumableInArrear(usage, targetDate, false,
+                                                                                                                           createMockBillingEvent(targetDate.toDateTimeAtStartOfDay(DateTimeZone.UTC)));
+
+        final List<InvoiceItem> existingUsage = Lists.newArrayList();
+        final UsageInvoiceItem ii1 = new UsageInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, usage.getName(), startDate, endDate, BigDecimal.TEN, currency);
+        existingUsage.add(ii1);
+        final UsageInvoiceItem ii2 = new UsageInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, usage.getName(), startDate, endDate, BigDecimal.TEN, currency);
+        existingUsage.add(ii2);
+
+        // Will be ignored as is starts one day earlier.
+        final UsageInvoiceItem ii3 = new UsageInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, usage.getName(), startDate.minusDays(1), endDate, BigDecimal.TEN, currency);
+        existingUsage.add(ii3);
+
+        // Will be ignored as it is for a different udsage section
+        final UsageInvoiceItem ii4 = new UsageInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, "other", startDate, endDate, BigDecimal.TEN, currency);
+        existingUsage.add(ii4);
+
+        // Will be ignored because non usage item
+        final FixedPriceInvoiceItem ii5 = new FixedPriceInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, BigDecimal.TEN, currency);
+        existingUsage.add(ii5);
+
+        final BigDecimal result = intervalConsumableInArrear.computeBilledUsage(startDate, endDate, existingUsage);
+        assertEquals(result, BigDecimal.TEN.add(BigDecimal.TEN));
+    }
+
+    @Test(groups = "fast")
+    public void testComputeBilledUsage() throws CatalogApiException {
+
+        final DefaultTieredBlock block1 = createDefaultTieredBlock("unit", 100, 10, BigDecimal.ONE);
+        final DefaultTier tier1 = createDefaultTier(block1);
+
+        final DefaultTieredBlock block2 = createDefaultTieredBlock("unit", 1000, 100, BigDecimal.ONE);
+        final DefaultTier tier2 = createDefaultTier(block2);
+        final DefaultUsage usage = createDefaultUsage(usageName, tier1, tier2);
+
+        final LocalDate targetDate = new LocalDate(2014, 03, 20);
+        final ContiguousIntervalConsumableInArrear intervalConsumableInArrear = createContiguousIntervalConsumableInArrear(usage, targetDate, false,
+                                                                                                                           createMockBillingEvent(targetDate.toDateTimeAtStartOfDay(DateTimeZone.UTC)));
+
+        final BigDecimal result = intervalConsumableInArrear.computeToBeBilledUsage(new BigDecimal("5325"), "unit");
+
+        // 5000 = 1000 (tier1) + 4325 (tier2) => 10 + 5 = 15
+        assertEquals(result, new BigDecimal("15"));
+    }
+
+    @Test(groups = "fast")
+    public void testComputeMissingItems() throws CatalogApiException {
+
+        final LocalDate startDate = new LocalDate(2014, 03, 20);
+        final LocalDate firstBCDDate = new LocalDate(2014, 04, 15);
+        final LocalDate endDate = new LocalDate(2014, 05, 15);
+
+        // 2 items for startDate - firstBCDDate
+        final RolledUpUsage usage1 = new DefaultRolledUpUsage(subscriptionId, "unit", startDate.toDateTimeAtStartOfDay(DateTimeZone.UTC), firstBCDDate.toDateTimeAtStartOfDay(DateTimeZone.UTC), new BigDecimal("130"));
+        final RolledUpUsage usage2 = new DefaultRolledUpUsage(subscriptionId, "unit", startDate.toDateTimeAtStartOfDay(DateTimeZone.UTC), firstBCDDate.toDateTimeAtStartOfDay(DateTimeZone.UTC), new BigDecimal("271"));
+
+        // 1 items for firstBCDDate - endDate
+        final RolledUpUsage usage3 = new DefaultRolledUpUsage(subscriptionId, "unit", firstBCDDate.toDateTimeAtStartOfDay(DateTimeZone.UTC), endDate.toDateTimeAtStartOfDay(DateTimeZone.UTC), new BigDecimal("199"));
+
+        final List<RolledUpUsage> usages = ImmutableList.<RolledUpUsage>builder().add(usage1).add(usage2).add(usage3).build();
+        this.mockUsageUserApi = createMockUsageUserApi(usages);
+
+        final DefaultTieredBlock block = createDefaultTieredBlock("unit", 100, 10, BigDecimal.ONE);
+        final DefaultTier tier = createDefaultTier(block);
+        final DefaultUsage usage = createDefaultUsage(usageName, tier);
+
+        final LocalDate targetDate = endDate;
+
+        final BillingEvent event1 = createMockBillingEvent(startDate.toDateTimeAtStartOfDay(DateTimeZone.UTC));
+        final BillingEvent event2 = createMockBillingEvent(endDate.toDateTimeAtStartOfDay(DateTimeZone.UTC));
+
+        final ContiguousIntervalConsumableInArrear intervalConsumableInArrear = createContiguousIntervalConsumableInArrear(usage, targetDate, true, event1, event2);
+
+        final List<InvoiceItem> invoiceItems = new ArrayList<InvoiceItem>();
+        InvoiceItem ii1 = new UsageInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, usage.getName(), startDate, firstBCDDate, BigDecimal.ONE, currency);
+        invoiceItems.add(ii1);
+
+        InvoiceItem ii2 = new UsageInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, usage.getName(), firstBCDDate, endDate, BigDecimal.ONE, currency);
+        invoiceItems.add(ii2);
+
+        final List<InvoiceItem> result = intervalConsumableInArrear.computeMissingItems(invoiceItems);
+        assertEquals(result.size(), 2);
+        // Invoiced for 1 BTC and used 130 + 271 = 401 => 5 blocks => 5 BTC so remaining piece should be 4 BTC
+        assertTrue(result.get(0).getAmount().compareTo(new BigDecimal("4.0")) == 0);
+        assertEquals(result.get(0).getCurrency(), Currency.BTC);
+        assertEquals(result.get(0).getAccountId(), accountId);
+        assertEquals(result.get(0).getBundleId(), bundleId);
+        assertEquals(result.get(0).getSubscriptionId(), subscriptionId);
+        assertEquals(result.get(0).getPlanName(), planName);
+        assertEquals(result.get(0).getPhaseName(), phaseName);
+        assertEquals(result.get(0).getUsageName(), usage.getName());
+        assertTrue(result.get(0).getStartDate().compareTo(startDate) == 0);
+        assertTrue(result.get(0).getEndDate().compareTo(firstBCDDate) == 0);
+
+        // Invoiced for 1 BTC and used 199  => 2 blocks => 2 BTC so remaining piece should be 1 BTC
+        assertTrue(result.get(1).getAmount().compareTo(new BigDecimal("1.0")) == 0);
+        assertEquals(result.get(1).getCurrency(), Currency.BTC);
+        assertEquals(result.get(1).getAccountId(), accountId);
+        assertEquals(result.get(1).getBundleId(), bundleId);
+        assertEquals(result.get(1).getSubscriptionId(), subscriptionId);
+        assertEquals(result.get(1).getPlanName(), planName);
+        assertEquals(result.get(1).getPhaseName(), phaseName);
+        assertEquals(result.get(1).getUsageName(), usage.getName());
+        assertTrue(result.get(1).getStartDate().compareTo(firstBCDDate) == 0);
+        assertTrue(result.get(1).getEndDate().compareTo(endDate) == 0);
+
+    }
+
+    private UsageUserApi createMockUsageUserApi(final List<RolledUpUsage> returnValue) {
+        final UsageUserApi result = Mockito.mock(UsageUserApi.class);
+        Mockito.when(result.getAllUsageForSubscription(Mockito.<UUID>any(), Mockito.<Set<String>>any(), Mockito.<List<DateTime>>any(), Mockito.<TenantContext>any())).thenReturn(returnValue);
+        return result;
+    }
+
+    private ContiguousIntervalConsumableInArrear createContiguousIntervalConsumableInArrear(final DefaultUsage usage, final LocalDate targetDate, final boolean closedInterval, final BillingEvent... events) {
+        final ContiguousIntervalConsumableInArrear intervalConsumableInArrear = new ContiguousIntervalConsumableInArrear(usage, invoiceId, mockUsageUserApi, targetDate, callContext);
+        for (BillingEvent event : events) {
+            intervalConsumableInArrear.addBillingEvent(event);
+        }
+        intervalConsumableInArrear.build(closedInterval);
+        return intervalConsumableInArrear;
+    }
+
+    private DefaultUsage createDefaultUsage(final String usageName, final DefaultTier... tiers) {
+        final DefaultUsage usage = new DefaultUsage();
+        usage.setName(usageName);
+        usage.setBillingMode(BillingMode.IN_ARREAR);
+        usage.setUsageType(UsageType.CONSUMABLE);
+        usage.setBillingPeriod(BillingPeriod.MONTHLY);
+        usage.setTiers(tiers);
+        return usage;
+    }
+
+    private DefaultTier createDefaultTier(final DefaultTieredBlock... blocks) {
+        DefaultTier tier = new DefaultTier();
+        tier.setBlocks(blocks);
+        return tier;
+    }
+
+    private DefaultTieredBlock createDefaultTieredBlock(final String unit, final int size, final int max, final BigDecimal btcPrice) {
+        final DefaultTieredBlock block = new DefaultTieredBlock();
+        block.setUnit(new DefaultUnit().setName(unit));
+        block.setSize(new Double(size));
+
+        final DefaultPrice[] prices = new DefaultPrice[1];
+        prices[0] = new DefaultPrice();
+        prices[0].setCurrency(Currency.BTC).setValue(btcPrice);
+
+        block.setPrice(new DefaultInternationalPrice().setPrices(prices));
+        block.setMax(new Double(max));
+        return block;
+    }
+
+    private BillingEvent createMockBillingEvent(DateTime effectiveDate) {
+        final BillingEvent result = Mockito.mock(BillingEvent.class);
+        Mockito.when(result.getCurrency()).thenReturn(Currency.BTC);
+        Mockito.when(result.getBillCycleDayLocal()).thenReturn(BCD);
+        Mockito.when(result.getTimeZone()).thenReturn(DateTimeZone.UTC);
+        Mockito.when(result.getEffectiveDate()).thenReturn(effectiveDate);
+
+        final Account account = Mockito.mock(Account.class);
+        Mockito.when(account.getId()).thenReturn(accountId);
+        Mockito.when(result.getAccount()).thenReturn(account);
+
+        final SubscriptionBase subscription = Mockito.mock(SubscriptionBase.class);
+        Mockito.when(subscription.getId()).thenReturn(subscriptionId);
+        Mockito.when(subscription.getBundleId()).thenReturn(bundleId);
+        Mockito.when(result.getSubscription()).thenReturn(subscription);
+
+        final Plan plan = Mockito.mock(Plan.class);
+        Mockito.when(plan.getName()).thenReturn("planName");
+        Mockito.when(result.getPlan()).thenReturn(plan);
+
+        final PlanPhase phase = Mockito.mock(PlanPhase.class);
+        Mockito.when(phase.getName()).thenReturn("phaseName");
+        Mockito.when(result.getPlanPhase()).thenReturn(phase);
+
+        return result;
+    }
+}
diff --git a/usage/src/main/java/org/killbill/billing/usage/api/user/DefaultUsageUserApi.java b/usage/src/main/java/org/killbill/billing/usage/api/user/DefaultUsageUserApi.java
index 112bb60..c685257 100644
--- a/usage/src/main/java/org/killbill/billing/usage/api/user/DefaultUsageUserApi.java
+++ b/usage/src/main/java/org/killbill/billing/usage/api/user/DefaultUsageUserApi.java
@@ -62,7 +62,8 @@ public class DefaultUsageUserApi implements UsageUserApi {
 
     @Override
     public List<RolledUpUsage> getAllUsageForSubscription(final UUID subscriptionId, final Set<String> unitTypes, final List<DateTime> transitionTimes, final TenantContext tenantContext) {
-        // STEPH_USAGE
+        // STEPH_USAGE implement
+        // STEPH_USAGE also dates should be inclusive/exclusive so as to not bill twice for last day
         return null;
     }
 }