killbill-aplcache

overdue: fix NPE in BillingStateCalculatorBundle When

7/12/2012 11:12:49 PM

Details

diff --git a/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java b/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java
index 64a3968..0bde914 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java
@@ -70,28 +70,38 @@ public class BillingStateCalculatorBundle extends BillingStateCalculator<Subscri
             }
             final PaymentResponse responseForLastFailedPayment = PaymentResponse.INSUFFICIENT_FUNDS; //TODO MDW
             final Tag[] tags = new Tag[]{}; //TODO MDW
-            final Product basePlanProduct = basePlan.getCurrentPlan().getProduct();
-            final BillingPeriod basePlanBillingPeriod = basePlan.getCurrentPlan().getBillingPeriod();
-            final PriceList basePlanPriceList = basePlan.getCurrentPriceList();
-            final PhaseType basePlanPhaseType = basePlan.getCurrentPhase().getPhaseType();
-
-
-            return new BillingStateBundle(
-                    id,
-                    numberOfUnpaidInvoices,
-                    unpaidInvoiceBalance,
-                    dateOfEarliestUnpaidInvoice,
-                    idOfEarliestUnpaidInvoice,
-                    responseForLastFailedPayment,
-                    tags,
-                    basePlanProduct,
-                    basePlanBillingPeriod,
-                    basePlanPriceList,
-                    basePlanPhaseType);
+
+            final Product basePlanProduct;
+            final BillingPeriod basePlanBillingPeriod;
+            final PriceList basePlanPriceList;
+            final PhaseType basePlanPhaseType;
+            if (basePlan.getCurrentPlan() == null) {
+                // The subscription has been cancelled since
+                basePlanProduct = null;
+                basePlanBillingPeriod = null;
+                basePlanPriceList = null;
+                basePlanPhaseType = null;
+            } else {
+                basePlanProduct = basePlan.getCurrentPlan().getProduct();
+                basePlanBillingPeriod = basePlan.getCurrentPlan().getBillingPeriod();
+                basePlanPriceList = basePlan.getCurrentPriceList();
+                basePlanPhaseType = basePlan.getCurrentPhase().getPhaseType();
+            }
+
+            return new BillingStateBundle(id,
+                                          numberOfUnpaidInvoices,
+                                          unpaidInvoiceBalance,
+                                          dateOfEarliestUnpaidInvoice,
+                                          idOfEarliestUnpaidInvoice,
+                                          responseForLastFailedPayment,
+                                          tags,
+                                          basePlanProduct,
+                                          basePlanBillingPeriod,
+                                          basePlanPriceList,
+                                          basePlanPhaseType);
         } catch (EntitlementUserApiException e) {
             throw new OverdueError(e);
         }
-
     }
 
     public SortedSet<Invoice> unpaidInvoicesForBundle(final UUID bundleId, final UUID accountId) {
diff --git a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
index 419e089..ed4bd61 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
@@ -53,10 +53,9 @@ public class OverdueWrapper<T extends Blockable> {
             return overdueStateSet.getClearState();
         }
 
-        final OverdueState<T> nextOverdueState;
         final BillingState<T> billingState = billingState();
         final String previousOverdueStateName = api.getBlockingStateFor(overdueable).getStateName();
-        nextOverdueState = overdueStateSet.calculateOverdueState(billingState, clock.getUTCNow());
+        final OverdueState<T> nextOverdueState = overdueStateSet.calculateOverdueState(billingState, clock.getUTCNow());
 
         if (nextOverdueState != null && !previousOverdueStateName.equals(nextOverdueState.getName())) {
             overdueStateApplicator.apply(overdueable, previousOverdueStateName, nextOverdueState);
diff --git a/overdue/src/test/java/com/ning/billing/overdue/calculator/TestBillingStateCalculatorBundle.java b/overdue/src/test/java/com/ning/billing/overdue/calculator/TestBillingStateCalculatorBundle.java
index 67b63ab..bb07af4 100644
--- a/overdue/src/test/java/com/ning/billing/overdue/calculator/TestBillingStateCalculatorBundle.java
+++ b/overdue/src/test/java/com/ning/billing/overdue/calculator/TestBillingStateCalculatorBundle.java
@@ -30,6 +30,8 @@ import org.testng.annotations.Test;
 
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+
 import com.ning.billing.catalog.MockPlan;
 import com.ning.billing.catalog.MockPriceList;
 import com.ning.billing.catalog.api.Plan;
@@ -57,6 +59,26 @@ public class TestBillingStateCalculatorBundle extends TestBillingStateCalculator
     }
 
     @Test(groups = "fast")
+    public void testBillingStateAfterCancellation() throws Exception {
+        Mockito.when(invoiceApi.getUnpaidInvoicesByAccountId(Mockito.<UUID>any(), Mockito.<DateTime>any())).thenReturn(ImmutableList.<Invoice>of());
+
+        final UUID bundleId = UUID.randomUUID();
+        final SubscriptionBundle bundle = Mockito.mock(SubscriptionBundle.class);
+        Mockito.when(bundle.getId()).thenReturn(bundleId);
+
+        final EntitlementUserApi entitlementApi = Mockito.mock(EntitlementUserApi.class);
+        final Subscription subscription = Mockito.mock(Subscription.class);
+        Mockito.when(entitlementApi.getBaseSubscription(bundleId)).thenReturn(subscription);
+
+        final BillingStateCalculatorBundle calc = new BillingStateCalculatorBundle(entitlementApi, invoiceApi, clock);
+        final BillingStateBundle billingStateBundle = calc.calculateBillingState(bundle);
+        Assert.assertNull(billingStateBundle.getBasePlanBillingPeriod());
+        Assert.assertNull(billingStateBundle.getBasePlanPhaseType());
+        Assert.assertNull(billingStateBundle.getBasePlanPriceList());
+        Assert.assertNull(billingStateBundle.getBasePlanProduct());
+    }
+
+    @Test(groups = "fast")
     public void testUnpaidInvoiceForBundle() {
         final UUID thisBundleId = new UUID(0L, 0L);
         final UUID thatBundleId = new UUID(0L, 1L);