killbill-memoizeit

Details

diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/transfer/DefaultEntitlementTransferApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/transfer/DefaultEntitlementTransferApi.java
index b9d5db4..f8d1f69 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/transfer/DefaultEntitlementTransferApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/transfer/DefaultEntitlementTransferApi.java
@@ -39,6 +39,7 @@ import com.ning.billing.entitlement.api.timeline.EntitlementTimelineApi;
 import com.ning.billing.entitlement.api.timeline.SubscriptionTimeline;
 import com.ning.billing.entitlement.api.timeline.SubscriptionTimeline.ExistingEvent;
 
+import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
 import com.ning.billing.entitlement.api.user.SubscriptionBuilder;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
@@ -217,6 +218,10 @@ public class DefaultEntitlementTransferApi extends EntitlementApiBase implements
 
             for (final SubscriptionTimeline cur : bundleTimeline.getSubscriptions()) {
                 final SubscriptionData oldSubscription = (SubscriptionData) dao.getSubscriptionFromId(cur.getId(), fromInternalCallContext);
+                // Skip already cancelled subscriptions
+                if (oldSubscription.getState() == SubscriptionState.CANCELLED) {
+                    continue;
+                }
                 final List<ExistingEvent> existingEvents = cur.getExistingEvents();
                 final ProductCategory productCategory = existingEvents.get(0).getPlanPhaseSpecifier().getProductCategory();
                 if (productCategory == ProductCategory.ADD_ON) {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/transfer/TestTransfer.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/transfer/TestTransfer.java
index f0dc1cd..21f7b6b 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/transfer/TestTransfer.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/transfer/TestTransfer.java
@@ -425,4 +425,52 @@ public class TestTransfer extends EntitlementTestSuiteWithEmbeddedDB {
         assertTrue(testListener.isCompleted(3000));
 
     }
+
+
+
+    @Test(groups = "slow")
+    public void testTransferWithAOCancelled() throws Exception {
+
+        final UUID newAccountId = UUID.randomUUID();
+
+        final String baseProduct = "Shotgun";
+        final BillingPeriod baseTerm = BillingPeriod.MONTHLY;
+        final String basePriceList = PriceListSet.DEFAULT_PRICELIST_NAME;
+
+        // CREATE BP
+        final Subscription baseSubscription = testUtil.createSubscription(bundle, baseProduct, baseTerm, basePriceList);
+
+        // MOVE 3 DAYS AND CREATE AO1
+        clock.addDays(3);
+        final String aoProduct1 = "Telescopic-Scope";
+        final BillingPeriod aoTerm1 = BillingPeriod.MONTHLY;
+        final SubscriptionData aoSubscription1 = testUtil.createSubscription(bundle, aoProduct1, aoTerm1, basePriceList);
+        assertEquals(aoSubscription1.getState(), SubscriptionState.ACTIVE);
+
+        testListener.pushExpectedEvent(NextEvent.PHASE);
+        testListener.pushExpectedEvent(NextEvent.PHASE);
+        clock.addDays(30);
+        assertTrue(testListener.isCompleted(3000));
+
+        // SET CTD TO TRIGGER CANCELLATION EOT
+        final DateTime ctd = baseSubscription.getStartDate().plusDays(30).plusMonths(1);
+        entitlementInternalApi.setChargedThroughDate(baseSubscription.getId(), ctd, internalCallContext);
+
+        // SET CTD TO TRIGGER CANCELLATION EOT
+        entitlementInternalApi.setChargedThroughDate(aoSubscription1.getId(), ctd, internalCallContext);
+
+        // CANCEL ADDON
+        aoSubscription1.cancel(clock.getUTCNow(), callContext);
+
+        clock.addDays(1);
+
+        final DateTime transferRequestedDate = clock.getUTCNow();
+        testListener.pushExpectedEvent(NextEvent.TRANSFER);
+        transferApi.transferBundle(bundle.getAccountId(), newAccountId, bundle.getExternalKey(), transferRequestedDate, true, false, callContext);
+        assertTrue(testListener.isCompleted(3000));
+
+        final SubscriptionBundle newBundle = entitlementApi.getBundleForAccountAndKey(newAccountId, bundle.getExternalKey(), callContext);
+        final List<Subscription> subscriptions = entitlementApi.getSubscriptionsForBundle(newBundle.getId(), callContext);
+        assertEquals(subscriptions.size(), 1);
+    }
 }