killbill-aplcache

invoice: Fix issue in usage capacity details (incorrect tier

2/7/2018 10:56:48 PM

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);