use of org.killbill.billing.jaxrs.json.BulkSubscriptionsBundleJson in project killbill by killbill.
the class SubscriptionResource method createSubscriptionsWithAddOnsInternal.
public Response createSubscriptionsWithAddOnsInternal(final List<BulkSubscriptionsBundleJson> entitlementsWithAddOns, final String entitlementDate, final String billingDate, final Boolean isMigrated, final Boolean skipResponse, final Boolean renameKeyIfExistsAndUnused, final Boolean callCompletion, final long timeoutSec, final List<String> pluginPropertiesString, final String createdBy, final String reason, final String comment, final HttpServletRequest request, final UriInfo uriInfo, final ObjectType responseObject) throws EntitlementApiException, AccountApiException, SubscriptionApiException {
Preconditions.checkArgument(Iterables.size(entitlementsWithAddOns) > 0, "No subscription specified to create");
final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final CallContext callContextNoAccountId = context.createCallContextNoAccountId(createdBy, reason, comment, request);
Preconditions.checkArgument(Iterables.size(entitlementsWithAddOns.get(0).getBaseEntitlementAndAddOns()) > 0, "SubscriptionJson body should be specified");
final Account account = accountUserApi.getAccountById(entitlementsWithAddOns.get(0).getBaseEntitlementAndAddOns().get(0).getAccountId(), callContextNoAccountId);
final CallContext callContext = context.createCallContextWithAccountId(account.getId(), createdBy, reason, comment, request);
final Collection<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
for (final BulkSubscriptionsBundleJson subscriptionsBundleJson : entitlementsWithAddOns) {
UUID bundleId = null;
String bundleExternalKey = null;
final Collection<EntitlementSpecifier> entitlementSpecifierList = new ArrayList<EntitlementSpecifier>();
for (final SubscriptionJson entitlement : subscriptionsBundleJson.getBaseEntitlementAndAddOns()) {
// verifications
verifyNonNullOrEmpty(entitlement, "SubscriptionJson body should be specified for each element");
if (entitlement.getPlanName() == null) {
verifyNonNullOrEmpty(entitlement.getProductName(), "SubscriptionJson productName needs to be set when no planName is specified", entitlement.getProductCategory(), "SubscriptionJson productCategory needs to be set when no planName is specified", entitlement.getBillingPeriod(), "SubscriptionJson billingPeriod needs to be set when no planName is specified", entitlement.getPriceList(), "SubscriptionJson priceList needs to be set when no planName is specified");
} else {
Preconditions.checkArgument(entitlement.getProductName() == null, "SubscriptionJson productName should not be set when planName is specified");
Preconditions.checkArgument(entitlement.getProductCategory() == null, "SubscriptionJson productCategory should not be set when planName is specified");
Preconditions.checkArgument(entitlement.getBillingPeriod() == null, "SubscriptionJson billingPeriod should not be set when planName is specified");
Preconditions.checkArgument(entitlement.getPriceList() == null, "SubscriptionJson priceList should not be set when planName is specified");
}
Preconditions.checkArgument(account.getId().equals(entitlement.getAccountId()), "SubscriptionJson accountId should be the same for each element");
// If set on one element, it should be set on all elements
Preconditions.checkArgument(bundleId == null || bundleId.equals(entitlement.getBundleId()), "SubscriptionJson bundleId should be the same for each element");
if (bundleId == null) {
bundleId = entitlement.getBundleId();
}
// Can be set on a single element (e.g. BASE + ADD_ON for a new bundle)
Preconditions.checkArgument(bundleExternalKey == null || entitlement.getBundleExternalKey() == null || bundleExternalKey.equals(entitlement.getBundleExternalKey()), "SubscriptionJson externalKey should be the same for each element");
if (bundleExternalKey == null) {
bundleExternalKey = entitlement.getBundleExternalKey();
}
// create the entitlementSpecifier
final EntitlementSpecifier spec = buildEntitlementSpecifier(entitlement, account.getCurrency(), entitlement.getExternalKey());
entitlementSpecifierList.add(spec);
}
final LocalDate resolvedEntitlementDate = toLocalDate(entitlementDate);
final LocalDate resolvedBillingDate = toLocalDate(billingDate);
final BaseEntitlementWithAddOnsSpecifier baseEntitlementSpecifierWithAddOns = buildBaseEntitlementWithAddOnsSpecifier(entitlementSpecifierList, resolvedEntitlementDate, resolvedBillingDate, bundleId, bundleExternalKey, isMigrated);
baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementSpecifierWithAddOns);
}
final EntitlementCallCompletionCallback<List<UUID>> callback = new EntitlementCallCompletionCallback<List<UUID>>() {
// By default, wait for invoice and payment
// This is very 101 and won't always work though: an entitlement plugin could override dates on the fly,
// an invoice plugin could reschedule the invoice generation, etc.
private boolean isImmediateOp = true;
@Override
public List<UUID> doOperation(final CallContext ctx) throws EntitlementApiException {
for (final BaseEntitlementWithAddOnsSpecifier spec : baseEntitlementWithAddOnsSpecifierList) {
if (spec.getBillingEffectiveDate() != null) {
final boolean inTheFuture = isInTheFuture(spec.getBillingEffectiveDate(), account);
if (inTheFuture) {
// At least one subscription has a billing date in the future: don't wait for any event
// We don't support callCompletion=true for a bulk creation call with dates all over the place
isImmediateOp = false;
break;
}
}
}
return entitlementApi.createBaseEntitlementsWithAddOns(account.getId(), baseEntitlementWithAddOnsSpecifierList, renameKeyIfExistsAndUnused, pluginProperties, callContext);
}
@Override
public boolean isImmOperation() {
return isImmediateOp;
}
@Override
public Response doResponseOk(final List<UUID> entitlementIds) {
if (responseObject == ObjectType.SUBSCRIPTION) {
return uriBuilder.buildResponse(uriInfo, SubscriptionResource.class, "getSubscription", Iterables.getFirst(entitlementIds, null), request);
}
// Workaround for https://github.com/killbill/killbill/issues/1336
// While we could tweak the container to support large number of bundles in the filter (e.g. Jetty's RequestBufferSize),
// the full list is probably not that useful for the client in practice.
final Collection<String> bundleIds = new LinkedHashSet<String>();
if (!skipResponse && entitlementIds.size() < MAX_NB_SUBSCRIPTIONS_TO_FOLLOW) {
try {
for (final Entitlement entitlement : entitlementApi.getAllEntitlementsForAccountId(account.getId(), callContext)) {
if (entitlementIds.contains(entitlement.getId())) {
bundleIds.add(entitlement.getBundleId().toString());
}
}
} catch (final EntitlementApiException e) {
return Response.status(Status.INTERNAL_SERVER_ERROR).build();
}
}
if (responseObject == ObjectType.ACCOUNT) {
return uriBuilder.buildResponse(uriInfo, AccountResource.class, "getAccountBundles", account.getId(), buildBundlesFilterQueryParam(bundleIds), request);
} else if (responseObject == ObjectType.BUNDLE) {
return uriBuilder.buildResponse(uriInfo, BundleResource.class, "getBundle", Iterables.getFirst(bundleIds, null), request);
} else {
throw new IllegalStateException("Unexpected input responseObject " + responseObject);
}
}
};
final EntitlementCallCompletion<List<UUID>> callCompletionCreation = new EntitlementCallCompletion<List<UUID>>();
return callCompletionCreation.withSynchronization(callback, timeoutSec, callCompletion, callContext);
}
Aggregations