diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SubscriptionResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SubscriptionResource.java
index a692dd6..3609a65 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SubscriptionResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SubscriptionResource.java
@@ -87,6 +87,8 @@ import org.killbill.commons.metrics.TimedResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
import com.google.inject.Inject;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
@@ -162,14 +164,28 @@ public class SubscriptionResource extends JaxRsResourceBase {
entitlement.getPriceList(), "SubscriptionJson priceList needs to be set");
final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
+ final CallContext callContext = context.createContext(createdBy, reason, comment, request);
+
+ SubscriptionBundle bundle = null;
final boolean createAddOnEntitlement = ProductCategory.ADD_ON.toString().equals(entitlement.getProductCategory());
if (createAddOnEntitlement) {
- verifyNonNullOrEmpty(entitlement.getBundleId(), "SubscriptionJson bundleId should be specified for ADD_ON");
+ final boolean expression = !Strings.isNullOrEmpty(entitlement.getExternalKey()) || !Strings.isNullOrEmpty(entitlement.getBundleId());
+ Preconditions.checkArgument(expression, "SubscriptionJson bundleId or externalKey should be specified for ADD_ON");
+ try {
+ if (!Strings.isNullOrEmpty(entitlement.getBundleId())) {
+ bundle = subscriptionApi.getSubscriptionBundle(UUID.fromString(entitlement.getBundleId()), callContext);
+ } else {
+ bundle = subscriptionApi.getActiveSubscriptionBundleForExternalKey(entitlement.getExternalKey(), callContext);
+ }
+ } catch (SubscriptionApiException e) {
+ // converting SubscriptionApiException to force this exception type
+ throw new IllegalArgumentException(e.getMessage());
+ }
} else {
verifyNonNullOrEmpty(entitlement.getAccountId(), "SubscriptionJson accountId should be specified for BP");
}
- final CallContext callContext = context.createContext(createdBy, reason, comment, request);
+ final UUID bundleId = (bundle != null) ? bundle.getId() : null;
final EntitlementCallCompletionCallback<Entitlement> callback = new EntitlementCallCompletionCallback<Entitlement>() {
@Override
@@ -181,7 +197,6 @@ public class SubscriptionResource extends JaxRsResourceBase {
BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList(), null);
final LocalDate inputLocalDate = toLocalDate(account, requestedDate, callContext);
- final UUID bundleId = entitlement.getBundleId() != null ? UUID.fromString(entitlement.getBundleId()) : null;
final PlanSpecifier planSpec = new PlanSpecifier(entitlement.getProductName(),
ProductCategory.valueOf(entitlement.getProductCategory()),
BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList());
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestEntitlement.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestEntitlement.java
index 33252d8..bb7c40d 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestEntitlement.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestEntitlement.java
@@ -31,9 +31,9 @@ import org.killbill.billing.catalog.api.BillingPeriod;
import org.killbill.billing.catalog.api.PhaseType;
import org.killbill.billing.catalog.api.PriceListSet;
import org.killbill.billing.catalog.api.ProductCategory;
-import org.killbill.billing.catalog.override.PriceOverride;
import org.killbill.billing.client.KillBillClientException;
import org.killbill.billing.client.model.Account;
+import org.killbill.billing.client.model.Bundle;
import org.killbill.billing.client.model.Invoice;
import org.killbill.billing.client.model.PhasePriceOverride;
import org.killbill.billing.client.model.Subscription;
@@ -228,4 +228,114 @@ public class TestEntitlement extends TestJaxrsBase {
assertEquals(invoices.get(0).getAmount().compareTo(BigDecimal.TEN), 0);
}
+ @Test(groups = "slow", description = "Create base and addOn subscription with bundle external key")
+ public void testBaseAndAddOnEntitlementsCreation() throws Exception {
+ final DateTime initialDate = new DateTime(2015, 11, 1, 0, 3, 42, 0);
+ clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
+
+ final Account accountJson = createAccountWithDefaultPaymentMethod();
+
+ final BillingPeriod term = BillingPeriod.MONTHLY;
+ final String externalKey = "bundleKey";
+
+ final Subscription baseEntitlementJson = createEntitlement(accountJson.getAccountId(), externalKey, "Shotgun",
+ ProductCategory.BASE, term, true);
+
+ final Subscription addOnEntitlementJson = createEntitlement(accountJson.getAccountId(), externalKey, "Telescopic-Scope",
+ ProductCategory.ADD_ON, term, true);
+
+ // Retrieves with GET
+ Bundle objFromJson = killBillClient.getBundle(externalKey);
+ final List<Subscription> subscriptions = objFromJson.getSubscriptions();
+
+ assertEquals(subscriptions.size(), 2);
+ assertTrue(baseEntitlementJson.equals(subscriptions.get(0)));
+ assertTrue(addOnEntitlementJson.equals(subscriptions.get(1)));
+
+ }
+
+ @Test(groups = "slow", description = "Create base and addOn subscription with bundle id")
+ public void testBaseAndAddOnEntitlementsCreationWithBundleId() throws Exception {
+ final DateTime initialDate = new DateTime(2015, 11, 1, 0, 3, 42, 0);
+ clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
+
+ final Account accountJson = createAccountWithDefaultPaymentMethod();
+
+ final BillingPeriod term = BillingPeriod.MONTHLY;
+ final String externalKey = "bundleKey";
+
+ final Subscription baseEntitlementJson = createEntitlement(accountJson.getAccountId(), externalKey, "Shotgun",
+ ProductCategory.BASE, term, true);
+
+ final Subscription input = new Subscription();
+ input.setAccountId(accountJson.getAccountId());
+ input.setBundleId(baseEntitlementJson.getBundleId());
+ input.setExternalKey("ignoreExternalkey");
+ input.setProductName("Telescopic-Scope");
+ input.setProductCategory(ProductCategory.ADD_ON);
+ input.setBillingPeriod(term);
+ input.setPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
+
+ final Subscription addOnEntitlementJson = killBillClient.createSubscription(input, DEFAULT_WAIT_COMPLETION_TIMEOUT_SEC, createdBy, reason, comment);
+
+ // Retrieves with GET
+ Bundle bundleJson = killBillClient.getBundle(externalKey);
+ final List<Subscription> subscriptions = bundleJson.getSubscriptions();
+
+ assertEquals(subscriptions.size(), 2);
+ assertTrue(baseEntitlementJson.equals(subscriptions.get(0)));
+ assertTrue(addOnEntitlementJson.equals(subscriptions.get(1)));
+
+ }
+
+ @Test(groups = "slow", description = "Try to create an ADD_ON subscription for an invalid bundle external key",
+ expectedExceptions = KillBillClientException.class, expectedExceptionsMessageRegExp = "Could not find a bundle matching key invalidKey")
+ public void testAddOnEntitlementInvalidKey() throws Exception {
+ final DateTime initialDate = new DateTime(2015, 11, 1, 0, 3, 42, 0);
+ clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
+
+ final Account accountJson = createAccountWithDefaultPaymentMethod();
+ createEntitlement(accountJson.getAccountId(), "invalidKey", "Telescopic-Scope",
+ ProductCategory.ADD_ON, BillingPeriod.MONTHLY, true);
+ }
+
+ @Test(groups = "slow", description = "Try to create an ADD_ON subscription for an invalid bundle external key",
+ expectedExceptions = KillBillClientException.class, expectedExceptionsMessageRegExp = "Object id=.* type=BUNDLE doesn't exist!")
+ public void testAddOnEntitlementInvalidBundleId() throws Exception {
+ final DateTime initialDate = new DateTime(2015, 11, 1, 0, 3, 42, 0);
+ clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
+
+ final Account accountJson = createAccountWithDefaultPaymentMethod();
+
+ final Subscription input = new Subscription();
+ input.setAccountId(accountJson.getAccountId());
+ input.setBundleId(UUID.randomUUID()); // <--- invalid bundleId
+ input.setProductName("Telescopic-Scope");
+ input.setProductCategory(ProductCategory.ADD_ON);
+ input.setBillingPeriod(BillingPeriod.MONTHLY);
+ input.setPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
+
+ killBillClient.createSubscription(input, DEFAULT_WAIT_COMPLETION_TIMEOUT_SEC, createdBy, reason, comment);
+ }
+
+ @Test(groups = "slow", description = "Try to create an ADD_ON subscription without bundle info",
+ expectedExceptions = KillBillClientException.class, expectedExceptionsMessageRegExp = "SubscriptionJson bundleId or externalKey should be specified for ADD_ON")
+ public void testAddOnEntitlementNoBundle() throws Exception {
+ final DateTime initialDate = new DateTime(2015, 11, 1, 0, 3, 42, 0);
+ clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
+
+ final Account accountJson = createAccountWithDefaultPaymentMethod();
+
+ final Subscription input = new Subscription();
+ input.setAccountId(accountJson.getAccountId());
+ input.setExternalKey(null);
+ input.setBundleId(null);
+ input.setProductName("Telescopic-Scope");
+ input.setProductCategory(ProductCategory.ADD_ON);
+ input.setBillingPeriod(BillingPeriod.MONTHLY);
+ input.setPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
+
+ killBillClient.createSubscription(input, DEFAULT_WAIT_COMPLETION_TIMEOUT_SEC, createdBy, reason, comment);
+ }
+
}