Details
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 a74bd6e..cf17f4d 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
@@ -195,7 +195,7 @@ public class ContiguousIntervalUsageInArrear {
final List<RolledUpUsage> allUsage = getRolledUpUsage();
for (final RolledUpUsage ru : allUsage) {
- int tierNum = 1;
+
List<UsageInArrearDetail> toBeBilledUsageDetails = Lists.newLinkedList();
BigDecimal toBeBilledUsage = BigDecimal.ZERO;
if (usage.getUsageType() == UsageType.CAPACITY) {
@@ -209,7 +209,7 @@ public class ContiguousIntervalUsageInArrear {
continue;
}
- toBeBilledUsageDetails.addAll(computeToBeBilledConsumableInArrear(cur, tierNum++));
+ toBeBilledUsageDetails.addAll(computeToBeBilledConsumableInArrear(cur));
}
}
@@ -424,28 +424,31 @@ public class ContiguousIntervalUsageInArrear {
* @throws CatalogApiException
*/
@VisibleForTesting
- List<UsageInArrearDetail> computeToBeBilledConsumableInArrear(final RolledUpUnit roUnit, int tierNum) throws CatalogApiException {
+ List<UsageInArrearDetail> computeToBeBilledConsumableInArrear(final RolledUpUnit roUnit) throws CatalogApiException {
Preconditions.checkState(isBuilt.get());
- final List<TieredBlock> tieredBlocks = getConsumableInArrearTieredBlocks(usage, roUnit.getUnitType());
+ final List<Map<Integer,TieredBlock>> tieredBlocksWithTierNum = getConsumableInArrearTieredBlocks(usage, roUnit.getUnitType());
switch (usage.getTierBlockPolicy()) {
case ALL_TIERS:
- return computeToBeBilledConsumableInArrearWith_ALL_TIERS(tieredBlocks, roUnit.getAmount(), tierNum);
+ return computeToBeBilledConsumableInArrearWith_ALL_TIERS(tieredBlocksWithTierNum, roUnit.getAmount());
case TOP_TIER:
- return Arrays.asList(computeToBeBilledConsumableInArrearWith_TOP_TIER(tieredBlocks, roUnit.getAmount(), tierNum));
+ return Arrays.asList(computeToBeBilledConsumableInArrearWith_TOP_TIER(tieredBlocksWithTierNum, roUnit.getAmount()));
default:
throw new IllegalStateException("Unknown TierBlockPolicy " + usage.getTierBlockPolicy());
}
}
- List<UsageInArrearDetail> computeToBeBilledConsumableInArrearWith_ALL_TIERS(final List<TieredBlock> tieredBlocks, final Long units, int tierNum) throws CatalogApiException {
+ List<UsageInArrearDetail> computeToBeBilledConsumableInArrearWith_ALL_TIERS(final List<Map<Integer,TieredBlock>> tieredBlocksWithTierNum, final Long units) throws CatalogApiException {
List<UsageInArrearDetail> toBeBilledDetails = Lists.newLinkedList();
BigDecimal result = BigDecimal.ZERO;
int remainingUnits = units.intValue();
- for (final TieredBlock tieredBlock : tieredBlocks) {
+ for (final Map<Integer,TieredBlock> tieredBlockWithTierNum : tieredBlocksWithTierNum) {
+
+ final TieredBlock tieredBlock = tieredBlockWithTierNum.entrySet().iterator().next().getValue();
+ final int tierNum = tieredBlockWithTierNum.entrySet().iterator().next().getKey();
final int blockTierSize = tieredBlock.getSize().intValue();
final int tmp = remainingUnits / blockTierSize + (remainingUnits % blockTierSize == 0 ? 0 : 1);
@@ -457,19 +460,27 @@ public class ContiguousIntervalUsageInArrear {
nbUsedTierBlocks = tmp;
remainingUnits = 0;
}
- toBeBilledDetails.add(new UsageInArrearDetail(tierNum, tieredBlock.getUnit().getName(), tieredBlock.getPrice().getPrice(getCurrency()), nbUsedTierBlocks));
+
+ if (nbUsedTierBlocks > 0) {
+ toBeBilledDetails.add(new UsageInArrearDetail(tierNum, tieredBlock.getUnit().getName(), tieredBlock.getPrice().getPrice(getCurrency()), nbUsedTierBlocks));
+ }
}
return toBeBilledDetails;
}
- UsageInArrearDetail computeToBeBilledConsumableInArrearWith_TOP_TIER(final List<TieredBlock> tieredBlocks, final Long units, int tierNum) throws CatalogApiException {
+ UsageInArrearDetail computeToBeBilledConsumableInArrearWith_TOP_TIER(final List<Map<Integer,TieredBlock>> tieredBlocksWithTierNum, final Long units) throws CatalogApiException {
int remainingUnits = units.intValue();
// By default last last tierBlock
- TieredBlock targetBlock = tieredBlocks.get(tieredBlocks.size() - 1);
+ Map<Integer,TieredBlock> targetBlockWithTierNum = tieredBlocksWithTierNum.get(tieredBlocksWithTierNum.size() - 1);
+ TieredBlock targetBlock = targetBlockWithTierNum.entrySet().iterator().next().getValue();
+ int targetTierNum = targetBlockWithTierNum.entrySet().iterator().next().getKey();
// Loop through all tier block
- for (final TieredBlock tieredBlock : tieredBlocks) {
+ for (final Map<Integer,TieredBlock> tieredBlockWithTierNum : tieredBlocksWithTierNum) {
+
+ final TieredBlock tieredBlock = tieredBlockWithTierNum.entrySet().iterator().next().getValue();
+ final int tierNum = tieredBlockWithTierNum.entrySet().iterator().next().getKey();
final int blockTierSize = tieredBlock.getSize().intValue();
final int tmp = remainingUnits / blockTierSize + (remainingUnits % blockTierSize == 0 ? 0 : 1);
@@ -477,13 +488,14 @@ public class ContiguousIntervalUsageInArrear {
remainingUnits -= tieredBlock.getMax() * blockTierSize;
} else {
targetBlock = tieredBlock;
+ targetTierNum = tierNum;
break;
}
}
final int lastBlockTierSize = targetBlock.getSize().intValue();
final int nbBlocks = units.intValue() / lastBlockTierSize + (units.intValue() % lastBlockTierSize == 0 ? 0 : 1);
- return new UsageInArrearDetail(tierNum, targetBlock.getUnit().getName(), targetBlock.getPrice().getPrice(getCurrency()), nbBlocks);
+ return new UsageInArrearDetail(targetTierNum, targetBlock.getUnit().getName(), targetBlock.getPrice().getPrice(getCurrency()), nbBlocks);
}
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
index 0a39859..0293bd6 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/usage/UsageUtils.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/usage/UsageUtils.java
@@ -16,8 +16,10 @@
package org.killbill.billing.invoice.usage;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.killbill.billing.catalog.api.BillingMode;
@@ -33,16 +35,20 @@ import com.google.common.collect.Lists;
public class UsageUtils {
- public static List<TieredBlock> getConsumableInArrearTieredBlocks(final Usage usage, final String unitType) {
+ public static List<Map<Integer,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();
+ final List<Map<Integer,TieredBlock>> result = Lists.newLinkedList();
+ int tierNum = 0;
for (Tier tier : usage.getTiers()) {
+ tierNum++;
for (TieredBlock tierBlock : tier.getTieredBlocks()) {
if (tierBlock.getUnit().getName().equals(unitType)) {
- result.add(tierBlock);
+ Map<Integer, TieredBlock> tieredBlockWithTierNum = new HashMap<>();
+ tieredBlockWithTierNum.put(tierNum, tierBlock);
+ result.add(tieredBlockWithTierNum);
}
}
}
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 1483fa4..00b825d 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
@@ -145,7 +145,7 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
Collections.<Usage>emptyList())
);
- List<UsageInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 111L), 1);
+ List<UsageInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 111L));
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<UsageInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 5325L), 1);
+ List<UsageInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 5325L));
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<UsageInArrearDetail> inputTier1 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 1000L), 1);
+ List<UsageInArrearDetail> inputTier1 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 1000L));
assertEquals(inputTier1.size(), 1);
// 1000 units => (tier1) : 1000 / 100 + 1000 % 100 = 10
assertEquals(inputTier1.get(0).getAmount(), new BigDecimal("10"));
- List<UsageInArrearDetail> inputTier2 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 101000L), 1);
+ List<UsageInArrearDetail> inputTier2 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 101000L));
assertEquals(inputTier2.size(), 1);
// 101000 units => (tier2) : 101000 / 1000 + 101000 % 1000 = 101 + 0 = 101
assertEquals(inputTier2.get(0).getAmount(), new BigDecimal("101"));
- List<UsageInArrearDetail> inputTier3 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 101001L), 1);
+ List<UsageInArrearDetail> inputTier3 = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 101001L));
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<UsageInArrearDetail> inputLastTier = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 300000L), 1);
+ List<UsageInArrearDetail> inputLastTier = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 300000L));
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<UsageInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 111L), 1);
+ List<UsageInArrearDetail> result = intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("unit", 111L));
assertEquals(result.size(), 1);
// 111 = 111 * 0.5 =
@@ -462,8 +462,8 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
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));
+ results.addAll(intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("cell-phone-minutes", 1000L)));
+ results.addAll(intervalConsumableInArrear.computeToBeBilledConsumableInArrear(new DefaultRolledUpUnit("Mbytes", 30720L)));
assertEquals(results.size(), 2);
assertEquals(intervalConsumableInArrear.toBeBilledForUnit(results), new BigDecimal("18.5"));