Skip to content

Commit

Permalink
subscription: fixes around STANDALONE support
Browse files Browse the repository at this point in the history
See killbill/killbill-integration-tests@7cbcdfd.

Signed-off-by: Pierre-Alexandre Meyer <pierre@mouraf.org>
  • Loading branch information
pierre committed Apr 20, 2018
1 parent 00ce8ff commit ac39dfd
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 89 deletions.
Expand Up @@ -643,10 +643,6 @@ protected void verifyNonNull(final Object... elements) {
} }
} }


protected void verifyNumberOfElements(int actual, int expected, String errorMessage) {
Preconditions.checkArgument(actual == expected, errorMessage);
}

protected void logDeprecationParameterWarningIfNeeded(@Nullable final String deprecatedParam, final String... replacementParams) { protected void logDeprecationParameterWarningIfNeeded(@Nullable final String deprecatedParam, final String... replacementParams) {
if (deprecatedParam != null) { if (deprecatedParam != null) {
log.warn(String.format("Parameter %s is being deprecated: Instead use parameters %s", deprecatedParam, Joiner.on(",").join(replacementParams))); log.warn(String.format("Parameter %s is being deprecated: Instead use parameters %s", deprecatedParam, Joiner.on(",").join(replacementParams)));
Expand Down
Expand Up @@ -28,6 +28,7 @@
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;


import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
Expand Down Expand Up @@ -107,6 +108,7 @@


import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.inject.Inject; import com.google.inject.Inject;
Expand Down Expand Up @@ -329,35 +331,53 @@ private Response createEntitlementsWithAddOnsInternal(final List<BulkSubscriptio


final Account account = accountUserApi.getAccountById(entitlementsWithAddOns.get(0).getBaseEntitlementAndAddOns().get(0).getAccountId(), callContext); final Account account = accountUserApi.getAccountById(entitlementsWithAddOns.get(0).getBaseEntitlementAndAddOns().get(0).getAccountId(), callContext);


final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>(); final Collection<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
for (BulkSubscriptionsBundleJson bulkBaseEntitlementWithAddOns : entitlementsWithAddOns) { for (final BulkSubscriptionsBundleJson bulkBaseEntitlementWithAddOns : entitlementsWithAddOns) {
final Iterable<SubscriptionJson> baseEntitlements = Iterables.filter( final Iterable<SubscriptionJson> baseEntitlements = Iterables.filter(
bulkBaseEntitlementWithAddOns.getBaseEntitlementAndAddOns(), new Predicate<SubscriptionJson>() { bulkBaseEntitlementWithAddOns.getBaseEntitlementAndAddOns(), new Predicate<SubscriptionJson>() {
@Override @Override
public boolean apply(final SubscriptionJson subscription) { public boolean apply(final SubscriptionJson subscription) {
return ProductCategory.BASE.toString().equalsIgnoreCase(subscription.getProductCategory()); return ProductCategory.BASE.toString().equalsIgnoreCase(subscription.getProductCategory());
} }
}); });
Preconditions.checkArgument(Iterables.size(baseEntitlements) > 0, "SubscriptionJson Base Entitlement needs to be provided");
verifyNumberOfElements(Iterables.size(baseEntitlements), 1, "Only one BASE product is allowed per bundle.");
final SubscriptionJson baseEntitlement = baseEntitlements.iterator().next();


final Iterable<SubscriptionJson> addonEntitlements = Iterables.filter( final List<EntitlementSpecifier> entitlementSpecifierList;
bulkBaseEntitlementWithAddOns.getBaseEntitlementAndAddOns(), new Predicate<SubscriptionJson>() { final String bundleExternalKey;
@Override if (baseEntitlements.iterator().hasNext()) {
public boolean apply(final SubscriptionJson subscription) { Preconditions.checkArgument(Iterables.size(baseEntitlements) == 1, "Only one BASE product is allowed per bundle.");
return ProductCategory.ADD_ON.toString().equalsIgnoreCase(subscription.getProductCategory());
} final SubscriptionJson baseEntitlement = baseEntitlements.iterator().next();
} final Iterable<SubscriptionJson> addonEntitlements = Iterables.filter(bulkBaseEntitlementWithAddOns.getBaseEntitlementAndAddOns(),
); new Predicate<SubscriptionJson>() {

@Override
final List<EntitlementSpecifier> entitlementSpecifierList = buildEntitlementSpecifierList(baseEntitlement, addonEntitlements, account.getCurrency()); public boolean apply(final SubscriptionJson subscription) {
return ProductCategory.ADD_ON.toString().equalsIgnoreCase(subscription.getProductCategory());
}
});

entitlementSpecifierList = buildEntitlementSpecifierList(baseEntitlement, addonEntitlements, account.getCurrency());
bundleExternalKey = baseEntitlement.getExternalKey();
} else {
final Collection<SubscriptionJson> standaloneEntitlements = Collections2.filter(bulkBaseEntitlementWithAddOns.getBaseEntitlementAndAddOns(),
new Predicate<SubscriptionJson>() {
@Override
public boolean apply(final SubscriptionJson subscription) {
return ProductCategory.STANDALONE.toString().equalsIgnoreCase(subscription.getProductCategory());
}
});
entitlementSpecifierList = buildEntitlementSpecifierList(standaloneEntitlements, account.getCurrency());
bundleExternalKey = standaloneEntitlements.isEmpty() ? null : standaloneEntitlements.iterator().next().getExternalKey();
}


// create the baseEntitlementSpecifierWithAddOns // create the baseEntitlementSpecifierWithAddOns
final LocalDate resolvedEntitlementDate = requestedDate != null ? toLocalDate(requestedDate) : toLocalDate(entitlementDate); final LocalDate resolvedEntitlementDate = requestedDate != null ? toLocalDate(requestedDate) : toLocalDate(entitlementDate);
final LocalDate resolvedBillingDate = requestedDate != null ? toLocalDate(requestedDate) : toLocalDate(billingDate); final LocalDate resolvedBillingDate = requestedDate != null ? toLocalDate(requestedDate) : toLocalDate(billingDate);


final BaseEntitlementWithAddOnsSpecifier baseEntitlementSpecifierWithAddOns = buildBaseEntitlementWithAddOnsSpecifier(entitlementSpecifierList, resolvedEntitlementDate, resolvedBillingDate, null, baseEntitlement, isMigrated); final BaseEntitlementWithAddOnsSpecifier baseEntitlementSpecifierWithAddOns = buildBaseEntitlementWithAddOnsSpecifier(entitlementSpecifierList,
resolvedEntitlementDate,
resolvedBillingDate,
bundleExternalKey,
isMigrated);
baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementSpecifierWithAddOns); baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementSpecifierWithAddOns);
} }


Expand Down Expand Up @@ -398,35 +418,15 @@ public Response doResponseOk(final List<UUID> entitlementIds) {
return callCompletionCreation.withSynchronization(callback, timeoutSec, callCompletion, callContext); return callCompletionCreation.withSynchronization(callback, timeoutSec, callCompletion, callContext);
} }


private List<EntitlementSpecifier> buildEntitlementSpecifierList(final SubscriptionJson baseEntitlement, final Iterable<SubscriptionJson> addonEntitlements, final Currency currency) { private List<EntitlementSpecifier> buildEntitlementSpecifierList(final SubscriptionJson baseEntitlement,
final Iterable<SubscriptionJson> addonEntitlements,
final Currency currency) {
final List<EntitlementSpecifier> entitlementSpecifierList = new ArrayList<EntitlementSpecifier>(); final List<EntitlementSpecifier> entitlementSpecifierList = new ArrayList<EntitlementSpecifier>();


// //
// BASE is fully specified we can add it // BASE or STANDALONE is fully specified, we can add it
// //
if (baseEntitlement.getPlanName() != null || buildEntitlementSpecifier(baseEntitlement, currency, entitlementSpecifierList);
(baseEntitlement.getProductName() != null &&
baseEntitlement.getProductCategory() != null &&
baseEntitlement.getBillingPeriod() != null &&
baseEntitlement.getPriceList() != null)) {
final PlanPhaseSpecifier planPhaseSpecifier = baseEntitlement.getPlanName() != null ?
new PlanPhaseSpecifier(baseEntitlement.getPlanName(), null) :
new PlanPhaseSpecifier(baseEntitlement.getProductName(),
BillingPeriod.valueOf(baseEntitlement.getBillingPeriod()), baseEntitlement.getPriceList(), null);
final List<PlanPhasePriceOverride> overrides = PhasePriceOverrideJson.toPlanPhasePriceOverrides(baseEntitlement.getPriceOverrides(), planPhaseSpecifier, currency);

EntitlementSpecifier specifier = new EntitlementSpecifier() {
@Override
public PlanPhaseSpecifier getPlanPhaseSpecifier() {
return planPhaseSpecifier;
}
@Override
public List<PlanPhasePriceOverride> getOverrides() {
return overrides;
}
};
entitlementSpecifierList.add(specifier);
}


for (final SubscriptionJson entitlement : addonEntitlements) { for (final SubscriptionJson entitlement : addonEntitlements) {
// verifications // verifications
Expand All @@ -438,49 +438,96 @@ public List<PlanPhasePriceOverride> getOverrides() {
entitlement.getPriceList(), "SubscriptionJson priceList needs to be set for each element"); entitlement.getPriceList(), "SubscriptionJson priceList needs to be set for each element");
} }
// create the entitlementSpecifier // create the entitlementSpecifier
final PlanPhaseSpecifier planPhaseSpecifier = entitlement.getPlanName() != null ? buildEntitlementSpecifier(entitlement, currency, entitlementSpecifierList);
new PlanPhaseSpecifier(entitlement.getPlanName(), null) : }
new PlanPhaseSpecifier(entitlement.getProductName(), return entitlementSpecifierList;
BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList(), null); }
final List<PlanPhasePriceOverride> overrides = PhasePriceOverrideJson.toPlanPhasePriceOverrides(entitlement.getPriceOverrides(), planPhaseSpecifier, currency);

private List<EntitlementSpecifier> buildEntitlementSpecifierList(final Iterable<SubscriptionJson> standaloneEntitlements,
EntitlementSpecifier specifier = new EntitlementSpecifier() { final Currency currency) {
@Override final List<EntitlementSpecifier> entitlementSpecifierList = new ArrayList<EntitlementSpecifier>();
public PlanPhaseSpecifier getPlanPhaseSpecifier() {
return planPhaseSpecifier; for (final SubscriptionJson standaloneEntitlement : standaloneEntitlements) {
} // verifications
@Override verifyNonNullOrEmpty(standaloneEntitlement, "SubscriptionJson body should be specified for each element");
public List<PlanPhasePriceOverride> getOverrides() { if (standaloneEntitlement.getPlanName() == null) {
return overrides; verifyNonNullOrEmpty(standaloneEntitlement.getProductName(), "SubscriptionJson productName needs to be set for each element",
} standaloneEntitlement.getProductCategory(), "SubscriptionJson productCategory needs to be set for each element",
}; standaloneEntitlement.getBillingPeriod(), "SubscriptionJson billingPeriod needs to be set for each element",
entitlementSpecifierList.add(specifier); standaloneEntitlement.getPriceList(), "SubscriptionJson priceList needs to be set for each element");
}
// create the entitlementSpecifier
buildEntitlementSpecifier(standaloneEntitlement, currency, entitlementSpecifierList);
} }
return entitlementSpecifierList; return entitlementSpecifierList;
} }


private BaseEntitlementWithAddOnsSpecifier buildBaseEntitlementWithAddOnsSpecifier(final List<EntitlementSpecifier> entitlementSpecifierList, final LocalDate resolvedEntitlementDate, final LocalDate resolvedBillingDate, final UUID bundleId, final SubscriptionJson baseEntitlement, final @QueryParam(QUERY_MIGRATED) @DefaultValue("false") Boolean isMigrated) { private void buildEntitlementSpecifier(final SubscriptionJson subscriptionJson,
final Currency currency,
final Collection<EntitlementSpecifier> entitlementSpecifierList) {
if (subscriptionJson.getPlanName() == null &&
(subscriptionJson.getProductName() == null ||
subscriptionJson.getProductCategory() == null ||
subscriptionJson.getBillingPeriod() == null ||
subscriptionJson.getPriceList() == null)) {
return;
}

final PlanPhaseSpecifier planPhaseSpecifier = subscriptionJson.getPlanName() != null ?
new PlanPhaseSpecifier(subscriptionJson.getPlanName(), null) :
new PlanPhaseSpecifier(subscriptionJson.getProductName(),
BillingPeriod.valueOf(subscriptionJson.getBillingPeriod()),
subscriptionJson.getPriceList(),
null);
final List<PlanPhasePriceOverride> overrides = PhasePriceOverrideJson.toPlanPhasePriceOverrides(subscriptionJson.getPriceOverrides(),
planPhaseSpecifier,
currency);

final EntitlementSpecifier specifier = new EntitlementSpecifier() {
@Override
public PlanPhaseSpecifier getPlanPhaseSpecifier() {
return planPhaseSpecifier;
}

@Override
public List<PlanPhasePriceOverride> getOverrides() {
return overrides;
}
};
entitlementSpecifierList.add(specifier);
}

private BaseEntitlementWithAddOnsSpecifier buildBaseEntitlementWithAddOnsSpecifier(final Iterable<EntitlementSpecifier> entitlementSpecifierList,
final LocalDate resolvedEntitlementDate,
final LocalDate resolvedBillingDate,
@Nullable final String bundleExternalKey,
final Boolean isMigrated) {
return new BaseEntitlementWithAddOnsSpecifier() { return new BaseEntitlementWithAddOnsSpecifier() {
@Override @Override
public UUID getBundleId() { public UUID getBundleId() {
return bundleId; return null;
} }

@Override @Override
public String getExternalKey() { public String getExternalKey() {
return baseEntitlement.getExternalKey(); return bundleExternalKey;
} }

@Override @Override
public Iterable<EntitlementSpecifier> getEntitlementSpecifier() { public Iterable<EntitlementSpecifier> getEntitlementSpecifier() {
return entitlementSpecifierList; return entitlementSpecifierList;
} }

@Override @Override
public LocalDate getEntitlementEffectiveDate() { public LocalDate getEntitlementEffectiveDate() {
return resolvedEntitlementDate; return resolvedEntitlementDate;
} }

@Override @Override
public LocalDate getBillingEffectiveDate() { public LocalDate getBillingEffectiveDate() {
return resolvedBillingDate; return resolvedBillingDate;
} }

@Override @Override
public boolean isMigrated() { public boolean isMigrated() {
return isMigrated; return isMigrated;
Expand Down

0 comments on commit ac39dfd

Please sign in to comment.