use of org.killbill.billing.entitlement.plugin.api.EntitlementContext in project killbill by killbill.
the class DefaultEntitlementApi method createBaseEntitlementsWithAddOns.
private List<UUID> createBaseEntitlementsWithAddOns(final OperationType operationType, final UUID accountId, final Iterable<BaseEntitlementWithAddOnsSpecifier> originalBaseEntitlementWithAddOnsSpecifiers, final boolean renameCancelledBundleIfExist, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
logCreateEntitlementsWithAOs(log, originalBaseEntitlementWithAddOnsSpecifiers);
final EntitlementContext pluginContext = new DefaultEntitlementContext(operationType, accountId, null, originalBaseEntitlementWithAddOnsSpecifiers, null, properties, callContext);
final WithEntitlementPlugin<List<UUID>> createBaseEntitlementsWithAddOns = new WithEntitlementPlugin<List<UUID>>() {
@Override
public List<UUID> doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(accountId, callContext);
final VersionedCatalog catalog;
try {
catalog = catalogInternalApi.getFullCatalog(true, true, contextWithValidAccountRecordId);
} catch (final CatalogApiException e) {
throw new EntitlementApiException(e);
}
final Map<UUID, Optional<EventsStream>> eventsStreamForBaseSubscriptionPerBundle = new HashMap<UUID, Optional<EventsStream>>();
final Map<String, Optional<UUID>> bundleKeyToIdMapping = new HashMap<String, Optional<UUID>>();
final Iterable<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifiersAfterPlugins = updatedPluginContext.getBaseEntitlementWithAddOnsSpecifiers();
final Collection<SubscriptionBaseWithAddOnsSpecifier> subscriptionBaseWithAddOnsSpecifiers = new LinkedList<SubscriptionBaseWithAddOnsSpecifier>();
DateTime upTo = null;
for (final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier : baseEntitlementWithAddOnsSpecifiersAfterPlugins) {
// Entitlement
final DateTime entitlementRequestedDate = dateHelper.fromLocalDateAndReferenceTime(baseEntitlementWithAddOnsSpecifier.getEntitlementEffectiveDate(), updatedPluginContext.getCreatedDate(), contextWithValidAccountRecordId);
upTo = upTo == null || upTo.compareTo(entitlementRequestedDate) < 0 ? entitlementRequestedDate : upTo;
final UUID bundleId = populateCaches(baseEntitlementWithAddOnsSpecifier, eventsStreamForBaseSubscriptionPerBundle, bundleKeyToIdMapping, catalog, callContext, contextWithValidAccountRecordId);
if (bundleId != null) {
final Optional<EventsStream> eventsStreamForBaseSubscription = eventsStreamForBaseSubscriptionPerBundle.get(bundleId);
if (eventsStreamForBaseSubscription.isPresent()) {
// Verify if the operation is valid for that bundle
preCheckAddEntitlement(bundleId, entitlementRequestedDate, baseEntitlementWithAddOnsSpecifier, eventsStreamForBaseSubscription.get());
}
}
final SubscriptionBaseWithAddOnsSpecifier subscriptionBaseWithAddOnsSpecifier = new SubscriptionBaseWithAddOnsSpecifier(baseEntitlementWithAddOnsSpecifier.getBundleId(), baseEntitlementWithAddOnsSpecifier.getBundleExternalKey(), baseEntitlementWithAddOnsSpecifier.getEntitlementSpecifier(), baseEntitlementWithAddOnsSpecifier.getBillingEffectiveDate(), baseEntitlementWithAddOnsSpecifier.isMigrated());
subscriptionBaseWithAddOnsSpecifiers.add(subscriptionBaseWithAddOnsSpecifier);
}
// Verify if operation is allowed by looking for is_block_change on Account
// Note that to fully check for block_change we should also look for BlockingState at the BUNDLE/SUBSCRIPTION level in case some of the input contain a BP that already exists.
checkForAccountBlockingChange(accountId, upTo, contextWithValidAccountRecordId);
final List<SubscriptionBaseWithAddOns> subscriptionsWithAddOns;
try {
subscriptionsWithAddOns = subscriptionBaseInternalApi.createBaseSubscriptionsWithAddOns(catalog, subscriptionBaseWithAddOnsSpecifiers, renameCancelledBundleIfExist, contextWithValidAccountRecordId);
} catch (final SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
}
// Update the context for plugins (assume underlying ordering is respected)
for (int i = 0; i < subscriptionsWithAddOns.size(); i++) {
final SubscriptionBaseWithAddOns subscriptionBaseWithAddOns = subscriptionsWithAddOns.get(i);
updatedPluginContext.getBaseEntitlementWithAddOnsSpecifiers(i).setBundleId(subscriptionBaseWithAddOns.getBundle().getId());
updatedPluginContext.getBaseEntitlementWithAddOnsSpecifiers(i).setBundleExternalKey(subscriptionBaseWithAddOns.getBundle().getExternalKey());
}
return createEntitlementEvents(baseEntitlementWithAddOnsSpecifiersAfterPlugins, subscriptionsWithAddOns, updatedPluginContext, contextWithValidAccountRecordId);
}
};
return pluginExecution.executeWithPlugin(createBaseEntitlementsWithAddOns, pluginContext);
}
use of org.killbill.billing.entitlement.plugin.api.EntitlementContext in project killbill by killbill.
the class DefaultSubscriptionApi method updateExternalKey.
@Override
public void updateExternalKey(final UUID bundleId, final String newExternalKey, final CallContext callContext) throws EntitlementApiException {
logUpdateExternalKey(log, bundleId, newExternalKey);
final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(bundleId, ObjectType.BUNDLE, callContext);
final ImmutableAccountData account;
try {
final UUID accountId = subscriptionBaseInternalApi.getAccountIdFromBundleId(bundleId, internalCallContext);
account = accountApi.getImmutableAccountDataById(accountId, internalCallContext);
} catch (final SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
} catch (AccountApiException e) {
throw new EntitlementApiException(e);
}
final LocalDate effectiveDate = internalCallContext.toLocalDate(callContext.getCreatedDate());
final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(bundleId, newExternalKey, new ArrayList<EntitlementSpecifier>(), effectiveDate, effectiveDate, false);
final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementWithAddOnsSpecifier);
final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.UPDATE_BUNDLE_EXTERNAL_KEY, account.getId(), null, baseEntitlementWithAddOnsSpecifierList, null, ImmutableList.<PluginProperty>of(), callContext);
final WithEntitlementPlugin<Void> updateExternalKeyWithPlugin = new WithEntitlementPlugin<Void>() {
final InternalCallContext internalCallContextWithValidAccountId = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
@Override
public Void doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
subscriptionBaseInternalApi.updateExternalKey(bundleId, newExternalKey, internalCallContextWithValidAccountId);
return null;
}
};
pluginExecution.executeWithPlugin(updateExternalKeyWithPlugin, pluginContext);
}
use of org.killbill.billing.entitlement.plugin.api.EntitlementContext in project killbill by killbill.
the class DefaultEntitlementApi method transferEntitlementsOverrideBillingPolicy.
@Override
public UUID transferEntitlementsOverrideBillingPolicy(final UUID sourceAccountId, final UUID destAccountId, final String bundleExternalKey, @Nullable final LocalDate effectiveDate, final BillingActionPolicy billingPolicy, final Iterable<PluginProperty> properties, final CallContext context) throws EntitlementApiException {
logTransferEntitlement(log, sourceAccountId, destAccountId, bundleExternalKey, effectiveDate, billingPolicy);
final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(null, bundleExternalKey, new ArrayList<EntitlementSpecifier>(), effectiveDate, effectiveDate, false);
final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementWithAddOnsSpecifier);
final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.TRANSFER_BUNDLE, sourceAccountId, destAccountId, baseEntitlementWithAddOnsSpecifierList, billingPolicy, properties, context);
final WithEntitlementPlugin<UUID> transferWithPlugin = new WithEntitlementPlugin<UUID>() {
@Override
public UUID doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
final boolean cancelImm;
switch(billingPolicy) {
case IMMEDIATE:
cancelImm = true;
break;
case END_OF_TERM:
cancelImm = false;
break;
default:
throw new RuntimeException("Unexpected billing policy " + billingPolicy);
}
final InternalCallContext contextWithSourceAccountRecordId = internalCallContextFactory.createInternalCallContext(sourceAccountId, context);
try {
final UUID activeSubscriptionIdForKey = entitlementUtils.getFirstActiveSubscriptionIdForKeyOrNull(bundleExternalKey, contextWithSourceAccountRecordId);
final UUID bundleId = activeSubscriptionIdForKey != null ? subscriptionBaseInternalApi.getBundleIdFromSubscriptionId(activeSubscriptionIdForKey, contextWithSourceAccountRecordId) : null;
final UUID baseBundleAccountId = bundleId != null ? subscriptionBaseInternalApi.getAccountIdFromBundleId(bundleId, contextWithSourceAccountRecordId) : null;
if (baseBundleAccountId == null || !baseBundleAccountId.equals(sourceAccountId)) {
throw new EntitlementApiException(new SubscriptionBaseApiException(ErrorCode.SUB_GET_INVALID_BUNDLE_KEY, bundleExternalKey));
}
final DefaultBaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = getFirstBaseEntitlementWithAddOnsSpecifier(updatedPluginContext.getBaseEntitlementWithAddOnsSpecifiers());
final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(baseEntitlementWithAddOnsSpecifier.getBillingEffectiveDate(), updatedPluginContext.getCreatedDate(), contextWithSourceAccountRecordId);
final SubscriptionBaseBundle newBundle = subscriptionBaseTransferApi.transferBundle(sourceAccountId, destAccountId, bundleExternalKey, requestedDate, true, cancelImm, context);
// Update the context for plugins
baseEntitlementWithAddOnsSpecifier.setBundleId(newBundle.getId());
baseEntitlementWithAddOnsSpecifier.setBundleExternalKey(newBundle.getExternalKey());
final Map<BlockingState, UUID> blockingStates = new HashMap<BlockingState, UUID>();
// Note that there is no un-transfer at the moment, so we effectively add a blocking state on disk for all subscriptions
for (final SubscriptionBase subscriptionBase : subscriptionBaseInternalApi.getSubscriptionsForBundle(bundleId, null, contextWithSourceAccountRecordId)) {
final BlockingState blockingState = new DefaultBlockingState(subscriptionBase.getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_CANCELLED, KILLBILL_SERVICES.ENTITLEMENT_SERVICE.getServiceName(), true, true, false, requestedDate);
blockingStates.put(blockingState, subscriptionBase.getBundleId());
}
entitlementUtils.setBlockingStateAndPostBlockingTransitionEvent(blockingStates, contextWithSourceAccountRecordId);
// Add blocking events for transferred subscriptions..
final InternalCallContext contextWithDestAccountRecordId = internalCallContextFactory.createInternalCallContext(destAccountId, context);
blockingStates.clear();
final DateTime entitlementRequestedDate = dateHelper.fromLocalDateAndReferenceTime(baseEntitlementWithAddOnsSpecifier.getEntitlementEffectiveDate(), updatedPluginContext.getCreatedDate(), contextWithDestAccountRecordId);
for (final SubscriptionBase subscriptionBase : subscriptionBaseInternalApi.getSubscriptionsForBundle(newBundle.getId(), null, contextWithDestAccountRecordId)) {
final BlockingState newBlockingState = new DefaultBlockingState(subscriptionBase.getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_START, KILLBILL_SERVICES.ENTITLEMENT_SERVICE.getServiceName(), false, false, false, entitlementRequestedDate);
blockingStates.put(newBlockingState, subscriptionBase.getBundleId());
}
entitlementUtils.setBlockingStateAndPostBlockingTransitionEvent(blockingStates, contextWithDestAccountRecordId);
return newBundle.getId();
} catch (final SubscriptionBaseTransferApiException e) {
throw new EntitlementApiException(e);
} catch (final SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
}
}
};
return pluginExecution.executeWithPlugin(transferWithPlugin, pluginContext);
}
use of org.killbill.billing.entitlement.plugin.api.EntitlementContext in project killbill by killbill.
the class DefaultEntitlement method changePlanOverrideBillingPolicy.
@Override
public Entitlement changePlanOverrideBillingPolicy(final EntitlementSpecifier spec, final LocalDate unused, final BillingActionPolicy actionPolicy, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
logChangePlan(log, this, spec, null, actionPolicy);
checkForPermissions(Permission.ENTITLEMENT_CAN_CHANGE_PLAN, callContext);
// Get the latest state from disk
refresh(callContext);
final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(getBundleId(), getBundleExternalKey(), null, null, null, false);
final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementWithAddOnsSpecifier);
final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CHANGE_PLAN, getAccountId(), null, baseEntitlementWithAddOnsSpecifierList, actionPolicy, properties, callContext);
final WithEntitlementPlugin<Entitlement> changePlanWithPlugin = new WithEntitlementPlugin<Entitlement>() {
@Override
public Entitlement doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
final DateTime resultingEffectiveDate;
try {
resultingEffectiveDate = subscriptionInternalApi.getDryRunChangePlanEffectiveDate(getSubscriptionBase(), spec, null, actionPolicy, context);
} catch (final SubscriptionBaseApiException e) {
throw new EntitlementApiException(e, e.getCode(), e.getMessage());
} catch (final CatalogApiException e) {
throw new EntitlementApiException(e, e.getCode(), e.getMessage());
}
try {
checker.checkBlockedChange(getSubscriptionBase(), resultingEffectiveDate, context);
} catch (final BlockingApiException e) {
throw new EntitlementApiException(e, e.getCode(), e.getMessage());
}
try {
getSubscriptionBase().changePlanWithPolicy(spec, actionPolicy, callContext);
} catch (final SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
}
final Collection<NotificationEvent> notificationEvents = new ArrayList<NotificationEvent>();
final Iterable<BlockingState> addOnsBlockingStates = computeAddOnBlockingStates(resultingEffectiveDate, notificationEvents, callContext, context);
// Record the new state first, then insert the notifications to avoid race conditions
setBlockingStates(addOnsBlockingStates, context);
for (final NotificationEvent notificationEvent : notificationEvents) {
recordFutureNotification(resultingEffectiveDate, notificationEvent, context);
}
return entitlementApi.getEntitlementForId(getId(), callContext);
}
};
return pluginExecution.executeWithPlugin(changePlanWithPlugin, pluginContext);
}
use of org.killbill.billing.entitlement.plugin.api.EntitlementContext in project killbill by killbill.
the class DefaultEntitlement method undoChangePlan.
@Override
public void undoChangePlan(final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
logUndoChangePlan(log, this);
checkForPermissions(Permission.ENTITLEMENT_CAN_CHANGE_PLAN, callContext);
// Get the latest state from disk
refresh(callContext);
final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(getBundleId(), getBundleExternalKey(), null, null, null, false);
final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementWithAddOnsSpecifier);
final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.UNDO_PENDING_SUBSCRIPTION_OPERATION, getAccountId(), null, baseEntitlementWithAddOnsSpecifierList, null, properties, callContext);
final WithEntitlementPlugin<Void> undoChangePlanEntitlementWithPlugin = new WithEntitlementPlugin<Void>() {
@Override
public Void doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
try {
getSubscriptionBase().undoChangePlan(callContext);
} catch (final SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
}
return null;
}
};
pluginExecution.executeWithPlugin(undoChangePlanEntitlementWithPlugin, pluginContext);
}
Aggregations