diff --git a/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableUsageInArrear.java b/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableUsageInArrear.java
index eabec9e..7e85038 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableUsageInArrear.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableUsageInArrear.java
@@ -197,7 +197,7 @@ public class ContiguousIntervalConsumableUsageInArrear extends ContiguousInterva
final int blockTierSize = tieredBlock.getSize().intValue();
final int tmp = remainingUnits / blockTierSize + (remainingUnits % blockTierSize == 0 ? 0 : 1);
int nbUsedTierBlocks;
- if (tmp > tieredBlock.getMax()) {
+ if (tieredBlock.getMax() != (double) -1 && tmp > tieredBlock.getMax() ) {
nbUsedTierBlocks = tieredBlock.getMax().intValue();
remainingUnits -= tieredBlock.getMax() * blockTierSize;
} else {
@@ -239,7 +239,7 @@ public class ContiguousIntervalConsumableUsageInArrear extends ContiguousInterva
tierNum++;
final int blockTierSize = tieredBlock.getSize().intValue();
final int tmp = remainingUnits / blockTierSize + (remainingUnits % blockTierSize == 0 ? 0 : 1);
- if (tmp > tieredBlock.getMax()) {
+ if ( tmp > tieredBlock.getMax()) { /* Includes the case where max is unlimited (-1) */
remainingUnits -= tieredBlock.getMax() * blockTierSize;
} else {
targetBlock = tieredBlock;
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 c2a883b..bc7f22c 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
@@ -221,6 +221,35 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
assertEquals(result.get(1).getAmount(), new BigDecimal("5"));
}
+
+ @Test(groups = "fast")
+ public void testComputeBilledUsageWithUnlimitedMaxWith_ALL_TIERS() throws CatalogApiException {
+
+ final DefaultTieredBlock block1 = createDefaultTieredBlock("unit", 100, 10, BigDecimal.ONE);
+ final DefaultTier tier1 = createDefaultTierWithBlocks(block1);
+
+ final DefaultTieredBlock block2 = createDefaultTieredBlock("unit", 1000, -1, BigDecimal.ONE);
+ final DefaultTier tier2 = createDefaultTierWithBlocks(block2);
+ final DefaultUsage usage = createConsumableInArrearUsage(usageName, BillingPeriod.MONTHLY, TierBlockPolicy.ALL_TIERS, tier1, tier2);
+
+ final LocalDate targetDate = new LocalDate(2014, 03, 20);
+
+ final ContiguousIntervalConsumableUsageInArrear intervalConsumableInArrear = createContiguousIntervalConsumableInArrear(usage, ImmutableList.<RawUsage>of(), targetDate, false,
+ createMockBillingEvent(targetDate.toDateTimeAtStartOfDay(DateTimeZone.UTC),
+ BillingPeriod.MONTHLY,
+ Collections.<Usage>emptyList())
+ );
+
+ List<UsageConsumableInArrearTierUnitAggregate> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 5325L), ImmutableList.<UsageConsumableInArrearTierUnitAggregate>of());
+ assertEquals(result.size(), 2);
+
+ // 5000 = 1000 (tier1) + 4325 (tier2) => 10 + 5 = 15
+ assertEquals(result.get(0).getAmount(), new BigDecimal("10"));
+ assertEquals(result.get(1).getAmount(), new BigDecimal("5"));
+ }
+
+
+
@Test(groups = "fast")
public void testComputeBilledUsageWith_TOP_TIER() throws CatalogApiException {
@@ -267,6 +296,37 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
assertEquals(inputLastTier.get(0).getAmount(), new BigDecimal("150.0"));
}
+
+ @Test(groups = "fast")
+ public void testComputeBilledUsageWithUnlimitedMaxWith_TOP_TIER() throws CatalogApiException {
+
+ final DefaultTieredBlock block1 = createDefaultTieredBlock("unit", 100, 10, BigDecimal.TEN);
+ final DefaultTier tier1 = createDefaultTierWithBlocks(block1);
+
+ final DefaultTieredBlock block2 = createDefaultTieredBlock("unit", 100, -1, BigDecimal.ONE);
+ final DefaultTier tier2 = createDefaultTierWithBlocks(block2);
+
+ final DefaultUsage usage = createConsumableInArrearUsage(usageName, BillingPeriod.MONTHLY, TierBlockPolicy.TOP_TIER, tier1, tier2);
+
+ final LocalDate targetDate = new LocalDate(2014, 03, 20);
+
+ final ContiguousIntervalConsumableUsageInArrear intervalConsumableInArrear = createContiguousIntervalConsumableInArrear(usage, ImmutableList.<RawUsage>of(), targetDate, false,
+ createMockBillingEvent(targetDate.toDateTimeAtStartOfDay(DateTimeZone.UTC),
+ BillingPeriod.MONTHLY,
+ Collections.<Usage>emptyList())
+ );
+ //
+ // 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<UsageConsumableInArrearTierUnitAggregate> inputTier1 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 2000L), ImmutableList.<UsageConsumableInArrearTierUnitAggregate>of());
+ // Target tier 2:
+ assertEquals(inputTier1.size(), 1);
+ assertEquals(inputTier1.get(0).getAmount(), new BigDecimal("20"));
+ }
+
+
+
+
@Test(groups = "fast")
public void testComputeBilledUsageSizeOneWith_TOP_TIER() throws CatalogApiException {