killbill-aplcache

Issue#839 - refactoring

2/1/2018 5:58:26 PM

Details

diff --git a/invoice/src/main/java/org/killbill/billing/invoice/config/MultiTenantInvoiceConfig.java b/invoice/src/main/java/org/killbill/billing/invoice/config/MultiTenantInvoiceConfig.java
index 98e14d7..bf83074 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/config/MultiTenantInvoiceConfig.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/config/MultiTenantInvoiceConfig.java
@@ -180,10 +180,11 @@ public class MultiTenantInvoiceConfig extends MultiTenantConfigBase implements I
             return UsageDetailMode.valueOf(result);
         }
 
-        if (mode.compareTo(UsageDetailMode.AGGREGATE) != 0 || mode.compareTo(UsageDetailMode.DETAIL) != 0) {
-            return UsageDetailMode.AGGREGATE;
+        if (mode == UsageDetailMode.AGGREGATE || mode == UsageDetailMode.DETAIL) {
+            return mode;
         }
-        return mode;
+
+        return UsageDetailMode.AGGREGATE;
     }
 
     @Override
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/InvoiceItemBase.java b/invoice/src/main/java/org/killbill/billing/invoice/model/InvoiceItemBase.java
index 329d2f1..b183ebe 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/InvoiceItemBase.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/InvoiceItemBase.java
@@ -72,21 +72,21 @@ public abstract class InvoiceItemBase extends EntityBase implements InvoiceItem 
 
     // For parent invoices
     public InvoiceItemBase(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, final UUID childAccountId,
-                             final BigDecimal amount, final Currency currency, final String description) {
+                           final BigDecimal amount, final Currency currency, final String description) {
         this(id, createdDate, invoiceId, accountId, childAccountId, null, null, description, null, null, amount, null, currency, null, null, null);
     }
 
     public InvoiceItemBase(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, @Nullable final UUID childAccountId, @Nullable final UUID bundleId,
-                            @Nullable final UUID subscriptionId, @Nullable final String description,
-                            @Nullable final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final BigDecimal rate, final Currency currency,
-                            final UUID reversedItemId){
+                           @Nullable final UUID subscriptionId, @Nullable final String description,
+                           @Nullable final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final BigDecimal rate, final Currency currency,
+                           final UUID reversedItemId) {
         this(id, createdDate, invoiceId, accountId, childAccountId, bundleId, subscriptionId, description, startDate, endDate, amount, rate, currency, reversedItemId, null, null);
     }
 
     private InvoiceItemBase(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, @Nullable final UUID childAccountId, @Nullable final UUID bundleId,
                             @Nullable final UUID subscriptionId, @Nullable final String description,
                             @Nullable final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final BigDecimal rate, final Currency currency,
-                            final UUID reversedItemId,@Nullable final Integer quantity,@Nullable final String itemDetails) {
+                            final UUID reversedItemId, @Nullable final Integer quantity, @Nullable final String itemDetails) {
         super(id, createdDate, createdDate);
         this.invoiceId = invoiceId;
         this.accountId = accountId;
@@ -154,13 +154,11 @@ public abstract class InvoiceItemBase extends EntityBase implements InvoiceItem 
         return linkedItemId;
     }
 
-
     @Override
     public UUID getChildAccountId() {
         return childAccountId;
     }
 
-
     @Override
     public String getPlanName() {
         return null;
@@ -192,10 +190,14 @@ public abstract class InvoiceItemBase extends EntityBase implements InvoiceItem 
     }
 
     @Override
-    public Integer getQuantity() { return quantity; }
+    public Integer getQuantity() {
+        return quantity;
+    }
 
     @Override
-    public String getItemDetails() { return itemDetails; }
+    public String getItemDetails() {
+        return itemDetails;
+    }
 
     @Override
     public boolean equals(final Object o) {
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 edb497f..c992206 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
@@ -49,7 +49,6 @@ import org.killbill.billing.junction.BillingEvent;
 import org.killbill.billing.usage.RawUsage;
 import org.killbill.billing.usage.api.RolledUpUnit;
 import org.killbill.billing.usage.api.RolledUpUsage;
-import org.killbill.billing.util.config.definition.InvoiceConfig;
 import org.killbill.billing.util.config.definition.InvoiceConfig.UsageDetailMode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -95,6 +94,7 @@ public class ContiguousIntervalUsageInArrear {
     private final LocalDate rawUsageStartDate;
     private final InternalTenantContext internalTenantContext;
     private final UsageDetailMode usageDetailMode;
+    private static final ObjectMapper objectMapper = new ObjectMapper();
 
     public ContiguousIntervalUsageInArrear(final Usage usage,
                                            final UUID accountId,
@@ -196,7 +196,7 @@ public class ContiguousIntervalUsageInArrear {
         final List<RolledUpUsage> allUsage = getRolledUpUsage();
         for (final RolledUpUsage ru : allUsage) {
             int tierNum = 1;
-            List<ConsumableInArrearDetail> toBeBilledUsageDetails = Lists.newLinkedList();
+            List<UsageInArrearDetail> toBeBilledUsageDetails = Lists.newLinkedList();
             BigDecimal toBeBilledUsage = BigDecimal.ZERO;
             if (usage.getUsageType() == UsageType.CAPACITY) {
                 toBeBilledUsageDetails.addAll(computeToBeBilledCapacityInArrear(ru.getRolledUpUnits(), tierNum));
@@ -225,8 +225,8 @@ public class ContiguousIntervalUsageInArrear {
                 final BigDecimal amountToBill = toBeBilledForUnit(toBeBilledUsageDetails);
 
                 if (amountToBill.compareTo(BigDecimal.ZERO) > 0) {
-                    if (UsageDetailMode.DETAIL.compareTo(usageDetailMode) == 0){
-                        for (ConsumableInArrearDetail toBeBilledUsageDetail : toBeBilledUsageDetails){
+                    if (UsageDetailMode.DETAIL == usageDetailMode){
+                        for (UsageInArrearDetail toBeBilledUsageDetail : toBeBilledUsageDetails){
                             final InvoiceItem item = new UsageInvoiceItem(invoiceId, accountId, getBundleId(), getSubscriptionId(), getPlanName(),
                                                                           getPhaseName(), usage.getName(), ru.getStart(), ru.getEnd(), toBeBilledUsageDetail.getAmount(), toBeBilledUsageDetail.getTierPrice(), getCurrency(),toBeBilledUsageDetail.getQuantity(),null);
                             result.add(item);
@@ -386,13 +386,13 @@ public class ContiguousIntervalUsageInArrear {
      * @throws CatalogApiException
      */
     @VisibleForTesting
-    List<ConsumableInArrearDetail> computeToBeBilledCapacityInArrear(final List<RolledUpUnit> roUnits, int tierNum) throws CatalogApiException {
+    List<UsageInArrearDetail> computeToBeBilledCapacityInArrear(final List<RolledUpUnit> roUnits, int tierNum) throws CatalogApiException {
         Preconditions.checkState(isBuilt.get());
 
         final List<Tier> tiers = getCapacityInArrearTier(usage);
 
         for (final Tier cur : tiers) {
-            List<ConsumableInArrearDetail> toBeBilledDetails = Lists.newLinkedList();
+            List<UsageInArrearDetail> toBeBilledDetails = Lists.newLinkedList();
             boolean complies = true;
             for (final RolledUpUnit ro : roUnits) {
                 final Limit tierLimit = getTierLimit(cur, ro.getUnitType());
@@ -402,7 +402,7 @@ public class ContiguousIntervalUsageInArrear {
                     complies = false;
                     break;
                 }
-                toBeBilledDetails.add(new ConsumableInArrearDetail(tierNum++, ro.getUnitType(), cur.getRecurringPrice().getPrice(getCurrency()), ro.getAmount().intValue(), BigDecimal.ZERO, null, null));
+                toBeBilledDetails.add(new UsageInArrearDetail(tierNum++, ro.getUnitType(), cur.getRecurringPrice().getPrice(getCurrency()), ro.getAmount().intValue(), BigDecimal.ZERO, null, null));
 
             }
             if (complies) {
@@ -423,7 +423,7 @@ public class ContiguousIntervalUsageInArrear {
      * @throws CatalogApiException
      */
     @VisibleForTesting
-    List<ConsumableInArrearDetail> computeToBeBilledConsumableInArrear(final RolledUpUnit roUnit, int tierNum) throws CatalogApiException {
+    List<UsageInArrearDetail> computeToBeBilledConsumableInArrear(final RolledUpUnit roUnit, int tierNum) throws CatalogApiException {
 
         Preconditions.checkState(isBuilt.get());
         final List<TieredBlock> tieredBlocks = getConsumableInArrearTieredBlocks(usage, roUnit.getUnitType());
@@ -439,9 +439,9 @@ public class ContiguousIntervalUsageInArrear {
     }
 
 
-    List<ConsumableInArrearDetail> computeToBeBilledConsumableInArrearWith_ALL_TIERS(final List<TieredBlock> tieredBlocks, final Long units, int tierNum) throws CatalogApiException {
+    List<UsageInArrearDetail> computeToBeBilledConsumableInArrearWith_ALL_TIERS(final List<TieredBlock> tieredBlocks, final Long units, int tierNum) throws CatalogApiException {
 
-        List<ConsumableInArrearDetail> toBeBilledDetails = Lists.newLinkedList();
+        List<UsageInArrearDetail> toBeBilledDetails = Lists.newLinkedList();
         BigDecimal result = BigDecimal.ZERO;
         int remainingUnits = units.intValue();
         for (final TieredBlock tieredBlock : tieredBlocks) {
@@ -456,12 +456,12 @@ public class ContiguousIntervalUsageInArrear {
                 nbUsedTierBlocks = tmp;
                 remainingUnits = 0;
             }
-            toBeBilledDetails.add(new ConsumableInArrearDetail(tierNum, tieredBlock.getUnit().getName(), tieredBlock.getPrice().getPrice(getCurrency()), nbUsedTierBlocks));
+            toBeBilledDetails.add(new UsageInArrearDetail(tierNum, tieredBlock.getUnit().getName(), tieredBlock.getPrice().getPrice(getCurrency()), nbUsedTierBlocks));
         }
         return toBeBilledDetails;
     }
 
-    ConsumableInArrearDetail computeToBeBilledConsumableInArrearWith_TOP_TIER(final List<TieredBlock> tieredBlocks, final Long units, int tierNum) throws CatalogApiException {
+    UsageInArrearDetail computeToBeBilledConsumableInArrearWith_TOP_TIER(final List<TieredBlock> tieredBlocks, final Long units, int tierNum) throws CatalogApiException {
 
         int remainingUnits = units.intValue();
 
@@ -482,7 +482,7 @@ public class ContiguousIntervalUsageInArrear {
         final int lastBlockTierSize = targetBlock.getSize().intValue();
         final int nbBlocks = units.intValue() / lastBlockTierSize + (units.intValue() % lastBlockTierSize == 0 ? 0 : 1);
 
-        return new ConsumableInArrearDetail(tierNum, targetBlock.getUnit().getName(), targetBlock.getPrice().getPrice(getCurrency()), nbBlocks);
+        return new UsageInArrearDetail(tierNum, targetBlock.getUnit().getName(), targetBlock.getPrice().getPrice(getCurrency()), nbBlocks);
     }
 
 
@@ -589,44 +589,43 @@ public class ContiguousIntervalUsageInArrear {
         }
     }
 
-    public BigDecimal toBeBilledForUnit(List<ConsumableInArrearDetail> toBeBilledDetails){
+    public BigDecimal toBeBilledForUnit(List<UsageInArrearDetail> toBeBilledDetails){
         BigDecimal result = BigDecimal.ZERO;
-        for (ConsumableInArrearDetail toBeBilled: toBeBilledDetails){
+        for (UsageInArrearDetail toBeBilled: toBeBilledDetails){
             result = result.add(toBeBilled.getAmount());
         }
         return result;
     }
 
-    private List<ConsumableInArrearDetail> reconcileExistedBilledWithToBeBilled(Iterable<InvoiceItem> billedItems, List<ConsumableInArrearDetail> toBeBilledConsumableInArrearDetails) {
+    private List<UsageInArrearDetail> reconcileExistedBilledWithToBeBilled(Iterable<InvoiceItem> billedItems, List<UsageInArrearDetail> toBeBilledUsageInArrearDetails) {
         for (final InvoiceItem bi : billedItems) {
-            List<ConsumableInArrearDetail> billedUsageItemDetails = fromJson(bi.getItemDetails());
+            List<UsageInArrearDetail> billedUsageItemDetails = fromJson(bi.getItemDetails());
 
             if (billedUsageItemDetails != null && billedUsageItemDetails.size() > 0) {
 
-                for (final ConsumableInArrearDetail toBeBilledConsumable : toBeBilledConsumableInArrearDetails) {
+                for (final UsageInArrearDetail toBeBilledConsumable : toBeBilledUsageInArrearDetails) {
                     billedUsageItemDetails = toBeBilledConsumable.reconcile(billedUsageItemDetails);
                 }
 
                 if (billedUsageItemDetails != null && billedUsageItemDetails.size() > 0) {
-                    for (final ConsumableInArrearDetail billedUsage : billedUsageItemDetails) {
-                        toBeBilledConsumableInArrearDetails.add(new ConsumableInArrearDetail(billedUsage.getTier(), billedUsage.getTierUnit(), billedUsage.getTierPrice(),
-                                                                            billedUsage.getQuantity(), billedUsage.getAmount().negate(), null, bi.getId().toString()));
+                    for (final UsageInArrearDetail billedUsage : billedUsageItemDetails) {
+                        toBeBilledUsageInArrearDetails.add(new UsageInArrearDetail(billedUsage.getTier(), billedUsage.getTierUnit(), billedUsage.getTierPrice(),
+                                                                                   billedUsage.getQuantity(), billedUsage.getAmount().negate(), null, bi.getId().toString()));
                     }
                 }
             } else {
-                toBeBilledConsumableInArrearDetails.add(new ConsumableInArrearDetail(bi.getRate(), bi.getQuantity(), bi.getAmount().negate(), bi.getId().toString()));
+                toBeBilledUsageInArrearDetails.add(new UsageInArrearDetail(bi.getRate(), bi.getQuantity(), bi.getAmount().negate(), bi.getId().toString()));
             }
         }
 
-        return toBeBilledConsumableInArrearDetails;
+        return toBeBilledUsageInArrearDetails;
     }
 
-    public static final String toJson(List<ConsumableInArrearDetail> toBeBilledConsumableInArrearDetails) {
+    private static final String toJson(List<UsageInArrearDetail> toBeBilledUsageInArrearDetails) {
         String result = null;
-        if (toBeBilledConsumableInArrearDetails != null && toBeBilledConsumableInArrearDetails.size() > 0){
-            ObjectMapper objectMapper = new ObjectMapper();
+        if (toBeBilledUsageInArrearDetails != null && toBeBilledUsageInArrearDetails.size() > 0){
             try {
-                result = objectMapper.writeValueAsString(toBeBilledConsumableInArrearDetails);
+                result = objectMapper.writeValueAsString(toBeBilledUsageInArrearDetails);
             } catch (JsonProcessingException e) {
                 Preconditions.checkState(false, e.getMessage());
             }
@@ -634,23 +633,20 @@ public class ContiguousIntervalUsageInArrear {
         return result;
     }
 
-    public static final List<ConsumableInArrearDetail> fromJson(String itemDetails){
-        List<ConsumableInArrearDetail> toBeBilledConsumableInArrearDetails = null;
+    private static final List<UsageInArrearDetail> fromJson(String itemDetails){
+        List<UsageInArrearDetail> toBeBilledUsageInArrearDetails = null;
         if (itemDetails != null){
-            ObjectMapper objectMapper = new ObjectMapper();
             try {
-                toBeBilledConsumableInArrearDetails = objectMapper.reader()
-                                           .forType(new TypeReference<List<ConsumableInArrearDetail>>() {})
-                                           .readValue(itemDetails);
+                toBeBilledUsageInArrearDetails = objectMapper.readValue(itemDetails, new TypeReference<List<UsageInArrearDetail>>() {});
             } catch (IOException e) {
                 Preconditions.checkState(false, e.getMessage());
             }
         }
 
-        return toBeBilledConsumableInArrearDetails;
+        return toBeBilledUsageInArrearDetails;
     }
 
-    public class ConsumableInArrearDetail {
+    public class UsageInArrearDetail {
 
         private final int tier;
         private final String tierUnit;
@@ -660,19 +656,19 @@ public class ContiguousIntervalUsageInArrear {
         private BigDecimal existingUsageAmount;
         private BigDecimal amount;
 
-        public ConsumableInArrearDetail(BigDecimal tierPrice, Integer quantity, BigDecimal existingUsageAmount, String reference){
+        public UsageInArrearDetail(BigDecimal tierPrice, Integer quantity, BigDecimal existingUsageAmount, String reference) {
             this(0, null, tierPrice, quantity, existingUsageAmount, BigDecimal.ZERO, reference);
         }
 
-        public ConsumableInArrearDetail(int tier, String tierUnit, BigDecimal tierPrice, Integer quantity){
+        public UsageInArrearDetail(int tier, String tierUnit, BigDecimal tierPrice, Integer quantity) {
             this(tier, tierUnit, tierPrice, quantity, tierPrice.multiply(new BigDecimal(quantity)), null, null);
         }
 
         @JsonCreator
-        public ConsumableInArrearDetail(@JsonProperty("tier") int tier, @JsonProperty("tierUnit") String tierUnit,
-                                        @JsonProperty("tierPrice") BigDecimal tierPrice, @JsonProperty("quantity") Integer quantity,
-                                        @JsonProperty("amount") BigDecimal amount, @JsonProperty("existingUsageAmount") BigDecimal existingUsageAmount,
-                                        @JsonProperty("reference") String reference){
+        public UsageInArrearDetail(@JsonProperty("tier") int tier, @JsonProperty("tierUnit") String tierUnit,
+                                   @JsonProperty("tierPrice") BigDecimal tierPrice, @JsonProperty("quantity") Integer quantity,
+                                   @JsonProperty("amount") BigDecimal amount, @JsonProperty("existingUsageAmount") BigDecimal existingUsageAmount,
+                                   @JsonProperty("reference") String reference) {
             this.tier = tier;
             this.tierUnit = tierUnit;
             this.tierPrice = tierPrice;
@@ -685,19 +681,27 @@ public class ContiguousIntervalUsageInArrear {
         public int getTier() {
             return tier;
         }
+
         public String getTierUnit() {
             return tierUnit;
         }
-        public BigDecimal getTierPrice() {
 
+        public BigDecimal getTierPrice() {
             return tierPrice;
         }
+
         public Integer getQuantity() {
             return quantity;
         }
+
         public BigDecimal getExistingUsageAmount() {
             return existingUsageAmount;
         }
+
+        public void setExistingUsageAmount(BigDecimal existingUsageAmount) {
+            this.existingUsageAmount = existingUsageAmount;
+        }
+
         public BigDecimal getAmount() {
             return amount;
         }
@@ -705,17 +709,15 @@ public class ContiguousIntervalUsageInArrear {
         public void setAmount(BigDecimal amount) {
             this.amount = amount;
         }
-        public void setExistingUsageAmount(BigDecimal existingUsageAmount) {
-            this.existingUsageAmount = existingUsageAmount;
-        }
+
         public void setReference(String reference) {
             this.reference = reference;
         }
 
-        public List<ConsumableInArrearDetail> reconcile(List<ConsumableInArrearDetail> billedUsageItemDetails){
-            List<ConsumableInArrearDetail> unreconciledUsage = Lists.newLinkedList();
-            for (ConsumableInArrearDetail billedUsageDetail : billedUsageItemDetails){
-                if( tierUnit == billedUsageDetail.tierUnit ) {
+        public List<UsageInArrearDetail> reconcile(List<UsageInArrearDetail> billedUsageItemDetails) {
+            List<UsageInArrearDetail> unreconciledUsage = Lists.newLinkedList();
+            for (UsageInArrearDetail billedUsageDetail : billedUsageItemDetails) {
+                if (tierUnit.equals(billedUsageDetail.tierUnit)) {
                     existingUsageAmount = billedUsageDetail.amount.abs();
                     amount = amount.subtract(existingUsageAmount);
                 } else {
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalCapacityInArrear.java b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalCapacityInArrear.java
index ed06f21..b37b357 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalCapacityInArrear.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalCapacityInArrear.java
@@ -26,7 +26,6 @@ import org.joda.time.DateTimeZone;
 import org.joda.time.LocalDate;
 import org.killbill.billing.catalog.DefaultLimit;
 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.BillingPeriod;
@@ -36,24 +35,20 @@ import org.killbill.billing.catalog.api.Usage;
 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.invoice.usage.ContiguousIntervalUsageInArrear.ConsumableInArrearDetail;
+import org.killbill.billing.invoice.usage.ContiguousIntervalUsageInArrear.UsageInArrearDetail;
 import org.killbill.billing.invoice.usage.ContiguousIntervalUsageInArrear.UsageInArrearItemsAndNextNotificationDate;
 import org.killbill.billing.junction.BillingEvent;
 import org.killbill.billing.usage.RawUsage;
 import org.killbill.billing.usage.api.RolledUpUnit;
-import org.killbill.billing.usage.api.RolledUpUsage;
 import org.killbill.billing.usage.api.svcs.DefaultRawUsage;
-import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
-import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
-import com.google.common.collect.Ordering;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
@@ -120,19 +115,23 @@ public class TestContiguousIntervalCapacityInArrear extends TestUsageInArrearBas
 
         final DefaultUnit unit1 = new DefaultUnit().setName("unit1");
         final DefaultUnit unit2 = new DefaultUnit().setName("unit2");
+        final DefaultUnit unit3 = new DefaultUnit().setName("unit3");
 
         final DefaultLimit limit1_1 = new DefaultLimit().setUnit(unit1).setMax((double) 100).setMin((double) -1);
         final DefaultLimit limit1_2 = new DefaultLimit().setUnit(unit2).setMax((double) 1000).setMin((double) -1);
-        final DefaultTier tier1 = createDefaultTierWithLimits(BigDecimal.TEN, limit1_1, limit1_2);
+        final DefaultLimit limit1_3 = new DefaultLimit().setUnit(unit3).setMax((double) 50).setMin((double) -1);
+        final DefaultTier tier1 = createDefaultTierWithLimits(BigDecimal.TEN, limit1_1, limit1_2, limit1_3);
 
         final DefaultLimit limit2_1 = new DefaultLimit().setUnit(unit1).setMax((double) 200).setMin((double) -1);
         final DefaultLimit limit2_2 = new DefaultLimit().setUnit(unit2).setMax((double) 2000).setMin((double) -1);
-        final DefaultTier tier2 = createDefaultTierWithLimits(new BigDecimal("20.0"), limit2_1, limit2_2);
+        final DefaultLimit limit2_3 = new DefaultLimit().setUnit(unit3).setMax((double) 100).setMin((double) -1);
+        final DefaultTier tier2 = createDefaultTierWithLimits(new BigDecimal("20.0"), limit2_1, limit2_2, limit2_3);
 
         // Don't define any max for last tier to allow any number
         final DefaultLimit limit3_1 = new DefaultLimit().setUnit(unit1).setMin((double) -1).setMax((double) -1);
         final DefaultLimit limit3_2 = new DefaultLimit().setUnit(unit2).setMin((double) -1).setMax((double) -1);
-        final DefaultTier tier3 = createDefaultTierWithLimits(new BigDecimal("30.0"), limit3_1, limit3_2);
+        final DefaultLimit limit3_3 = new DefaultLimit().setUnit(unit3).setMax((double) -1).setMin((double) -1);
+        final DefaultTier tier3 = createDefaultTierWithLimits(new BigDecimal("30.0"), limit3_1, limit3_2, limit3_3);
 
 
         final DefaultUsage usage = createCapacityInArrearUsage(usageName, BillingPeriod.MONTHLY, tier1, tier2, tier3);
@@ -145,8 +144,10 @@ public class TestContiguousIntervalCapacityInArrear extends TestUsageInArrearBas
                                                                                                                                                   Collections.<Usage>emptyList())
                                                                                                                      );
         // Tier 1 (both units from tier 1)
-        List<ConsumableInArrearDetail> result = intervalCapacityInArrear.computeToBeBilledCapacityInArrear(ImmutableList.<RolledUpUnit>of(new DefaultRolledUpUnit("unit1", 100L),
-                                                                                                                                          new DefaultRolledUpUnit("unit2", 1000L)), 1);
+        List<UsageInArrearDetail> result = intervalCapacityInArrear.computeToBeBilledCapacityInArrear(ImmutableList.<RolledUpUnit>of(new DefaultRolledUpUnit("unit1", 100L),
+                                                                                                                                     new DefaultRolledUpUnit("unit2", 1000L),
+                                                                                                                                     new DefaultRolledUpUnit("unit3", 50L)), 1);
+        assertEquals(result.size(), 3);
         assertEquals(intervalCapacityInArrear.toBeBilledForUnit(result), BigDecimal.TEN);
 
         // Tier 2 (only one unit from tier 1)
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 1351ae4..1483fa4 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
@@ -37,7 +37,7 @@ import org.killbill.billing.catalog.api.Usage;
 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.invoice.usage.ContiguousIntervalUsageInArrear.ConsumableInArrearDetail;
+import org.killbill.billing.invoice.usage.ContiguousIntervalUsageInArrear.UsageInArrearDetail;
 import org.killbill.billing.invoice.usage.ContiguousIntervalUsageInArrear.UsageInArrearItemsAndNextNotificationDate;
 import org.killbill.billing.junction.BillingEvent;
 import org.killbill.billing.usage.RawUsage;
@@ -145,7 +145,7 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
                                                                                                                                              Collections.<Usage>emptyList())
                                                                                                                      );
 
-        List<ConsumableInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 111L), 1);
+        List<UsageInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 111L), 1);
         assertEquals(result.size(), 3);
         // 111 = 10 (tier1) + 100 (tier2) + 1 (tier3) => 10 * 1.5 + 100 * 1 + 1 * 0.5 = 115.5
         assertEquals(result.get(0).getAmount(), new BigDecimal("15.0"));
@@ -173,7 +173,7 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
                                                                                                                                              Collections.<Usage>emptyList())
                                                                                                                      );
 
-        List<ConsumableInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 5325L),1);
+        List<UsageInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 5325L), 1);
         assertEquals(result.size(), 2);
 
         // 5000 = 1000 (tier1) + 4325 (tier2) => 10 + 5 = 15
@@ -207,23 +207,23 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
         //
         // In this model unit amount is first used to figure out which tier we are in, and then we price all unit at that 'target' tier
         //
-        List<ConsumableInArrearDetail> inputTier1 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 1000L), 1);
+        List<UsageInArrearDetail> inputTier1 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 1000L), 1);
         assertEquals(inputTier1.size(), 1);
         // 1000 units => (tier1) : 1000 / 100 + 1000 % 100 = 10
         assertEquals(inputTier1.get(0).getAmount(), new BigDecimal("10"));
 
-        List<ConsumableInArrearDetail> inputTier2 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 101000L), 1);
+        List<UsageInArrearDetail> inputTier2 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 101000L), 1);
         assertEquals(inputTier2.size(), 1);
         // 101000 units => (tier2) :  101000 / 1000 + 101000 % 1000 = 101 + 0 = 101
         assertEquals(inputTier2.get(0).getAmount(), new BigDecimal("101"));
 
-        List<ConsumableInArrearDetail> inputTier3 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 101001L), 1);
+        List<UsageInArrearDetail> inputTier3 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 101001L), 1);
         assertEquals(inputTier3.size(), 1);
         // 101001 units => (tier3) : 101001 / 1000 + 101001 % 1000 = 101 + 1 = 102 units => $51
         assertEquals(inputTier3.get(0).getAmount(), new BigDecimal("51.0"));
 
         // If we pass the maximum of the last tier, we price all units at the last tier
-        List<ConsumableInArrearDetail> inputLastTier = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 300000L), 1);
+        List<UsageInArrearDetail> inputLastTier = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 300000L), 1);
         assertEquals(inputLastTier.size(), 1);
         // 300000 units => (tier3) : 300000 / 1000 + 300000 % 1000 = 300 units => $150
         assertEquals(inputLastTier.get(0).getAmount(), new BigDecimal("150.0"));
@@ -252,7 +252,7 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
                                                                                                                                              Collections.<Usage>emptyList())
                                                                                                                      );
 
-        List<ConsumableInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 111L),1);
+        List<UsageInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 111L), 1);
         assertEquals(result.size(), 1);
 
         // 111 = 111 * 0.5 =
@@ -320,9 +320,8 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
         assertTrue(result.get(0).getEndDate().compareTo(firstBCDDate) == 0);
 
         // check item detail
-        List<MockToBeBilledConsumableInArrearDetail> itemDetails = objectMapper.reader()
-                                                                 .forType(new TypeReference<List<MockToBeBilledConsumableInArrearDetail>>() {})
-                                                                 .readValue(result.get(0).getItemDetails());
+        List<MockToBeBilledConsumableInArrearDetail> itemDetails = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<List<MockToBeBilledConsumableInArrearDetail>>() {});
+
         assertEquals(itemDetails.size(), 2);
         assertEquals(itemDetails.get(0).getAmount().compareTo(new BigDecimal("5")),0);
         assertEquals(itemDetails.get(1).getAmount().compareTo(new BigDecimal("-1")),0);
@@ -341,9 +340,7 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
         assertTrue(result.get(1).getEndDate().compareTo(endDate) == 0);
 
         // check item detail
-        List<MockToBeBilledConsumableInArrearDetail> itemDetails2 = objectMapper.reader()
-                                                                  .forType(new TypeReference<List<MockToBeBilledConsumableInArrearDetail>>() {})
-                                                                  .readValue(result.get(1).getItemDetails());
+        List<MockToBeBilledConsumableInArrearDetail> itemDetails2 = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<List<MockToBeBilledConsumableInArrearDetail>>() {});
         assertEquals(itemDetails2.size(), 2);
         assertEquals(itemDetails2.get(0).getAmount().compareTo(new BigDecimal("2")),0);
         assertEquals(itemDetails2.get(1).getAmount().compareTo(new BigDecimal("-1")),0);
@@ -450,6 +447,28 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
         assertEquals(res.getTransitionTimes().size(), 0);
     }
 
+    @Test(groups = "fast")
+    public void testTobeBilledForUnit() throws CatalogApiException {
+
+        final DefaultTieredBlock block1 = createDefaultTieredBlock("cell-phone-minutes", 1000, 10000, new BigDecimal("0.5"));
+        final DefaultTieredBlock block2 = createDefaultTieredBlock("Mbytes", 512, 512000, new BigDecimal("0.3"));
+        final DefaultTier tier = createDefaultTierWithBlocks(block1, block2);
+
+        final DefaultUsage usage = createConsumableInArrearUsage(usageName, BillingPeriod.MONTHLY, TierBlockPolicy.ALL_TIERS, tier);
+        final LocalDate targetDate = new LocalDate(2014, 03, 20);
+        final ContiguousIntervalUsageInArrear intervalConsumableInArrear = createContiguousIntervalConsumableInArrear(usage, ImmutableList.<RawUsage>of(), targetDate, false,
+                                                                                                                      createMockBillingEvent(targetDate.toDateTimeAtStartOfDay(DateTimeZone.UTC),
+                                                                                                                                             BillingPeriod.MONTHLY,
+                                                                                                                                             Collections.<Usage>emptyList())
+                                                                                                                     );
+        List<UsageInArrearDetail> results = Lists.newArrayList();
+        results.addAll(intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("cell-phone-minutes", 1000L), 1));
+        results.addAll(intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("Mbytes", 30720L), 2));
+        assertEquals(results.size(), 2);
+
+        assertEquals(intervalConsumableInArrear.toBeBilledForUnit(results), new BigDecimal("18.5"));
+    }
+
     public static class MockToBeBilledConsumableInArrearDetail {
 
         private final int tier;