killbill-memoizeit

subscription: CR for 03588f3646. See #724. Allow to pass

3/27/2017 4:58:40 PM

Details

diff --git a/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultEntitlementApi.java b/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultEntitlementApi.java
index 2e1c12c..5eb96de 100644
--- a/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultEntitlementApi.java
+++ b/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultEntitlementApi.java
@@ -791,7 +791,7 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
         entitlementApi.createBaseEntitlementsWithAddOns(account.getId(), baseEntitlementWithAddOnsSpecifiers, ImmutableList.<PluginProperty>of(), callContext);
     }
 
-    @Test(groups = "slow", expectedExceptions = IllegalArgumentException.class)
+    @Test(groups = "slow")
     public void testCreateBaseSubscriptionsWithAddOnsBadOrdering() throws AccountApiException, EntitlementApiException, SubscriptionApiException {
         final LocalDate initialDate = new LocalDate(2013, 8, 7);
         clock.setDay(initialDate);
@@ -806,6 +806,10 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
 
         final Iterable<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifiers = ImmutableList.of(baseEntitlementWithAddOnsSpecifier1);
 
+
+        testListener.pushExpectedEvents(NextEvent.BLOCK, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.CREATE);
         entitlementApi.createBaseEntitlementsWithAddOns(account.getId(), baseEntitlementWithAddOnsSpecifiers, ImmutableList.<PluginProperty>of(), callContext);
+        assertListenerStatus();
+
     }
 }
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
index 5b3b8d5..d3bdedf 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
@@ -257,40 +257,34 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
         return subscriptions;
     }
 
-    private boolean isBaseSpecified(final Catalog catalog, final BaseEntitlementWithAddOnsSpecifier entitlementWithAddOnsSpecifier, final DateTime effectiveDate) throws SubscriptionBaseApiException {
+    private boolean sanityAndReorderBPSpecFirst(final Catalog catalog, final BaseEntitlementWithAddOnsSpecifier entitlementWithAddOnsSpecifier, final DateTime effectiveDate, final List<EntitlementSpecifier> outputEntitlementSpecifier) throws SubscriptionBaseApiException {
 
-        // We expect input to be correctly ordered where BP is first
-        final Iterator<EntitlementSpecifier> iterator = entitlementWithAddOnsSpecifier.getEntitlementSpecifier().iterator();
-        if (!iterator.hasNext()) {
-            throw new IllegalArgumentException("createBaseSubscriptionsWithAddOns should contain at least one specifier!");
-        }
 
-        final EntitlementSpecifier firstPlanSpecifier = iterator.next();
+        EntitlementSpecifier basePlanSpecifier = null;
+        final List<EntitlementSpecifier> addOnSpecifiers = new ArrayList<EntitlementSpecifier>();
         try {
-            // Look for BASE plan in the first entry
-            final Plan plan = catalog.createOrFindPlan(firstPlanSpecifier.getPlanPhaseSpecifier(), null, effectiveDate);
-            final boolean isBaseSpecified = plan.getProduct().getCategory() == ProductCategory.BASE;
-
-            // If there is no BASE as a first entry, validate it is not in the subsequent entries
-            if (!isBaseSpecified) {
-                if (Iterables.any(entitlementWithAddOnsSpecifier.getEntitlementSpecifier(), new Predicate<EntitlementSpecifier>() {
-                    @Override
-                    public boolean apply(final EntitlementSpecifier input) {
-                        try {
-                            final Plan inputPlan = catalog.createOrFindPlan(input.getPlanPhaseSpecifier(), null, effectiveDate);
-                            return inputPlan.getProduct().getCategory() == ProductCategory.BASE;
-                        } catch (CatalogApiException e) {
-                            throw new IllegalArgumentException(String.format("createBaseSubscriptionsWithAddOns plan='%s' does not exist", input.getPlanPhaseSpecifier().getPlanName()));
-                        }
+            for (final EntitlementSpecifier cur : entitlementWithAddOnsSpecifier.getEntitlementSpecifier()) {
+                final Plan inputPlan = catalog.createOrFindPlan(cur.getPlanPhaseSpecifier(), null, effectiveDate);
+                final boolean isBaseSpecifier = inputPlan.getProduct().getCategory() == ProductCategory.BASE;
+                if (isBaseSpecifier) {
+                    if (basePlanSpecifier == null) {
+                        basePlanSpecifier =  cur;
+                    } else {
+                        throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_INVALID_ENTITLEMENT_SPECIFIER);
                     }
-                })) {
-                    throw new IllegalArgumentException("createBaseSubscriptionsWithAddOns BASE plan should be first in the list of specifier");
+                } else {
+                    addOnSpecifiers.add(cur);
                 }
             }
-            return isBaseSpecified;
         } catch (final CatalogApiException e) {
             throw new SubscriptionBaseApiException(e);
         }
+
+        if (basePlanSpecifier != null) {
+            outputEntitlementSpecifier.add(basePlanSpecifier);
+        }
+        outputEntitlementSpecifier.addAll(addOnSpecifiers);
+        return basePlanSpecifier != null;
     }
 
 
@@ -307,8 +301,12 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
                                                DefaultClock.truncateMs(entitlementWithAddOnsSpecifier.getBillingEffectiveDate().toDateTimeAtStartOfDay()) : now;
 
 
+
+                final List<EntitlementSpecifier> reorderedSpecifiers = new ArrayList<EntitlementSpecifier>();
+                final boolean isBaseSpecifierExists = sanityAndReorderBPSpecFirst(catalog, entitlementWithAddOnsSpecifier, effectiveDate, reorderedSpecifiers);
+
                 final SubscriptionBaseBundle bundle;
-                if (isBaseSpecified(catalog, entitlementWithAddOnsSpecifier, effectiveDate)) {
+                if (isBaseSpecifierExists) {
                     bundle = createBundleForAccount(accountId, entitlementWithAddOnsSpecifier.getExternalKey(), context);
                 } else {
                     final List<SubscriptionBaseBundle> existingBundles = dao.getSubscriptionBundlesForKey(entitlementWithAddOnsSpecifier.getExternalKey(), context);
@@ -327,7 +325,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
                         effectiveDate,
                         verifyAndBuildSubscriptionSpecifiers(bundle.getId(),
                                                              bundle.getExternalKey(),
-                                                             entitlementWithAddOnsSpecifier.getEntitlementSpecifier(),
+                                                             reorderedSpecifiers,
                                                              entitlementWithAddOnsSpecifier.isMigrated(),
                                                              context,
                                                              now,