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 b49d684..d391b05 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
@@ -390,10 +390,12 @@ public class ContiguousIntervalUsageInArrear {
Preconditions.checkState(isBuilt.get());
final List<Tier> tiers = getCapacityInArrearTier(usage);
+
+ final Set<String> perUnitTypeDetailTierLevel = new HashSet<String>();
int tierNum = 0;
+ final List<UsageInArrearDetail> toBeBilledDetails = Lists.newLinkedList();
for (final Tier cur : tiers) {
tierNum++;
- List<UsageInArrearDetail> toBeBilledDetails = Lists.newLinkedList();
boolean complies = true;
for (final RolledUpUnit ro : roUnits) {
final Limit tierLimit = getTierLimit(cur, ro.getUnitType());
@@ -401,10 +403,12 @@ public class ContiguousIntervalUsageInArrear {
// Specifying a -1 value for last max tier will make the validation works
if (tierLimit.getMax() != (double) -1 && ro.getAmount().doubleValue() > tierLimit.getMax()) {
complies = false;
- break;
+ } else {
+ if (!perUnitTypeDetailTierLevel.contains(ro.getUnitType())) {
+ toBeBilledDetails.add(new UsageInArrearDetail(tierNum, ro.getUnitType(), cur.getRecurringPrice().getPrice(getCurrency()), ro.getAmount().intValue(), BigDecimal.ZERO, BigDecimal.ZERO, ""));
+ perUnitTypeDetailTierLevel.add(ro.getUnitType());
+ }
}
- toBeBilledDetails.add(new UsageInArrearDetail(tierNum, ro.getUnitType(), cur.getRecurringPrice().getPrice(getCurrency()), ro.getAmount().intValue(), BigDecimal.ZERO, BigDecimal.ZERO, ""));
-
}
if (complies) {
toBeBilledDetails.get(toBeBilledDetails.size() - 1).setAmount(cur.getRecurringPrice().getPrice(getCurrency()));
@@ -443,7 +447,6 @@ public class ContiguousIntervalUsageInArrear {
List<UsageInArrearDetail> computeToBeBilledConsumableInArrearWith_ALL_TIERS(final List<TieredBlock> tieredBlocks, final Long units) throws CatalogApiException {
List<UsageInArrearDetail> toBeBilledDetails = Lists.newLinkedList();
- BigDecimal result = BigDecimal.ZERO;
int remainingUnits = units.intValue();
int tierNum = 0;
for (final TieredBlock tieredBlock : tieredBlocks) {
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 69baa60..efb2388 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,10 +16,8 @@
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;
@@ -40,13 +38,19 @@ public class UsageUtils {
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()) {
+ boolean found = false;
for (TieredBlock tierBlock : tier.getTieredBlocks()) {
if (tierBlock.getUnit().getName().equals(unitType)) {
result.add(tierBlock);
+ found = true;
+ break;
}
}
+ // We expect this method to return an ordered list of TieredBlock, each for each tier.
+ Preconditions.checkState(found, String.format("Catalog issue in usage section '%s': Missing tierBlock definition for unit '%s'", usage.getName(), unitType));
}
return result;
}
@@ -65,7 +69,6 @@ public class UsageUtils {
return result;
}
-
public static List<Tier> getCapacityInArrearTier(final Usage usage) {
Preconditions.checkArgument(usage.getBillingMode() == BillingMode.IN_ARREAR && usage.getUsageType() == UsageType.CAPACITY);
@@ -73,7 +76,6 @@ public class UsageUtils {
return ImmutableList.copyOf(usage.getTiers());
}
-
public static Set<String> getCapacityInArrearUnitTypes(final Usage usage) {
Preconditions.checkArgument(usage.getBillingMode() == BillingMode.IN_ARREAR && usage.getUsageType() == UsageType.CAPACITY);
@@ -88,5 +90,4 @@ public class UsageUtils {
return result;
}
-
}
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 14cbf50..b29d079 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
@@ -292,15 +292,16 @@ public class TestContiguousIntervalCapacityInArrear extends TestUsageInArrearBas
assertEquals(result.get(0).getAmount().compareTo(BigDecimal.TEN),0, String.format("%s != 10.0", result.get(0).getAmount()));
itemDetails = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<List<UsageInArrearDetail>>() {});
- // BAR item detail
- assertEquals(itemDetails.get(0).getTierUnit(), "BAR");
- assertEquals(itemDetails.get(0).getTier(), 2);
- assertEquals(itemDetails.get(0).getQuantity().intValue(), 101);
- assertEquals(itemDetails.get(0).getTierPrice().compareTo(BigDecimal.TEN), 0);
// FOO item detail
- assertEquals(itemDetails.get(1).getTierUnit(), "FOO");
+ assertEquals(itemDetails.get(0).getTierUnit(), "FOO");
+ assertEquals(itemDetails.get(0).getTier(), 1);
+ assertEquals(itemDetails.get(0).getQuantity().intValue(), 5);
+ assertEquals(itemDetails.get(0).getTierPrice().compareTo(BigDecimal.ONE), 0);
+
+ // BAR item detail
+ assertEquals(itemDetails.get(1).getTierUnit(), "BAR");
assertEquals(itemDetails.get(1).getTier(), 2);
- assertEquals(itemDetails.get(1).getQuantity().intValue(), 5);
+ assertEquals(itemDetails.get(1).getQuantity().intValue(), 101);
assertEquals(itemDetails.get(1).getTierPrice().compareTo(BigDecimal.TEN), 0);
// Case 3
@@ -314,9 +315,9 @@ public class TestContiguousIntervalCapacityInArrear extends TestUsageInArrearBas
itemDetails = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<List<UsageInArrearDetail>>() {});
// BAR item detail
assertEquals(itemDetails.get(0).getTierUnit(), "BAR");
- assertEquals(itemDetails.get(0).getTier(), 3);
+ assertEquals(itemDetails.get(0).getTier(), 2);
assertEquals(itemDetails.get(0).getQuantity().intValue(), 101);
- assertEquals(itemDetails.get(0).getTierPrice().compareTo(new BigDecimal("100.0")), 0);
+ assertEquals(itemDetails.get(0).getTierPrice().compareTo(new BigDecimal("10.0")), 0);
// FOO item detail
assertEquals(itemDetails.get(1).getTierUnit(), "FOO");
assertEquals(itemDetails.get(1).getTier(), 3);