use of org.killbill.notificationq.api.NotificationEvent in project killbill by killbill.
the class DefaultEntitlement method cancelEntitlementWithDateOverrideBillingPolicy.
// See also EntitlementInternalApi#cancel for the bulk API
@Override
public Entitlement cancelEntitlementWithDateOverrideBillingPolicy(@Nullable final LocalDate entitlementEffectiveDate, final BillingActionPolicy billingPolicy, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
logCancelEntitlement(log, this, entitlementEffectiveDate, null, null, billingPolicy);
checkForPermissions(Permission.ENTITLEMENT_CAN_CANCEL, callContext);
// Get the latest state from disk
refresh(callContext);
final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(getBundleId(), getExternalKey(), null, entitlementEffectiveDate, entitlementEffectiveDate, false);
final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementWithAddOnsSpecifier);
final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CANCEL_SUBSCRIPTION, getAccountId(), null, baseEntitlementWithAddOnsSpecifierList, billingPolicy, properties, callContext);
final WithEntitlementPlugin<Entitlement> cancelEntitlementWithPlugin = new WithEntitlementPlugin<Entitlement>() {
@Override
public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
if (eventsStream.isEntitlementCancelled()) {
throw new EntitlementApiException(ErrorCode.SUB_CANCEL_BAD_STATE, getId(), EntitlementState.CANCELLED);
}
final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
try {
// Cancel subscription base first, to correctly compute the add-ons entitlements we need to cancel (see below)
getSubscriptionBase().cancelWithPolicy(billingPolicy, eventsStream.getAccountTimeZone(), eventsStream.getDefaultBillCycleDayLocal(), callContext);
} catch (final SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
}
final DateTime effectiveCancelDate = dateHelper.fromLocalDateAndReferenceTimeWithMinimum(entitlementEffectiveDate, getEventsStream().getEntitlementEffectiveStartDateTime(), contextWithValidAccountRecordId);
final BlockingState newBlockingState = new DefaultBlockingState(getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_CANCELLED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, false, effectiveCancelDate);
final Collection<NotificationEvent> notificationEvents = new ArrayList<NotificationEvent>();
final Collection<BlockingState> addOnsBlockingStates = computeAddOnBlockingStates(effectiveCancelDate, notificationEvents, callContext, contextWithValidAccountRecordId);
// Record the new state first, then insert the notifications to avoid race conditions
setBlockingStates(newBlockingState, addOnsBlockingStates, contextWithValidAccountRecordId);
for (final NotificationEvent notificationEvent : notificationEvents) {
recordFutureNotification(effectiveCancelDate, notificationEvent, contextWithValidAccountRecordId);
}
return entitlementApi.getEntitlementForId(getId(), callContext);
}
};
return pluginExecution.executeWithPlugin(cancelEntitlementWithPlugin, pluginContext);
}
use of org.killbill.notificationq.api.NotificationEvent in project killbill by killbill.
the class DefaultEntitlement method changePlanWithDate.
@Override
public Entitlement changePlanWithDate(final PlanSpecifier spec, final List<PlanPhasePriceOverride> overrides, @Nullable final LocalDate effectiveDate, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
logChangePlan(log, this, spec, overrides, effectiveDate, null);
checkForPermissions(Permission.ENTITLEMENT_CAN_CHANGE_PLAN, callContext);
// Get the latest state from disk
refresh(callContext);
final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(getBundleId(), getExternalKey(), null, effectiveDate, effectiveDate, false);
final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementWithAddOnsSpecifier);
final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CHANGE_PLAN, getAccountId(), null, baseEntitlementWithAddOnsSpecifierList, null, properties, callContext);
final WithEntitlementPlugin<Entitlement> changePlanWithPlugin = new WithEntitlementPlugin<Entitlement>() {
@Override
public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
if (!eventsStream.isEntitlementActive()) {
throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), getState());
}
final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
final DateTime effectiveChangeDate = dateHelper.fromLocalDateAndReferenceTime(updatedPluginContext.getBaseEntitlementWithAddOnsSpecifiers().iterator().next().getBillingEffectiveDate(), context);
final DateTime resultingEffectiveDate;
try {
resultingEffectiveDate = subscriptionInternalApi.getDryRunChangePlanEffectiveDate(getSubscriptionBase(), spec, effectiveChangeDate, null, overrides, 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().changePlanWithDate(spec, overrides, resultingEffectiveDate, 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.notificationq.api.NotificationEvent in project killbill by killbill.
the class DefaultEntitlement method changePlanOverrideBillingPolicy.
@Override
public Entitlement changePlanOverrideBillingPolicy(final PlanSpecifier spec, final List<PlanPhasePriceOverride> overrides, final LocalDate entitlementEffectiveDate, final BillingActionPolicy actionPolicy, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
logChangePlan(log, this, spec, overrides, entitlementEffectiveDate, actionPolicy);
checkForPermissions(Permission.ENTITLEMENT_CAN_CHANGE_PLAN, callContext);
// Get the latest state from disk
refresh(callContext);
final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(getBundleId(), getExternalKey(), null, entitlementEffectiveDate, 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 EntitlementContext updatedPluginContext) throws EntitlementApiException {
if (!eventsStream.isEntitlementActive()) {
throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), getState());
}
final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
final DateTime effectiveChangeDate;
try {
effectiveChangeDate = subscriptionInternalApi.getDryRunChangePlanEffectiveDate(getSubscriptionBase(), spec, null, actionPolicy, overrides, 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(), effectiveChangeDate, context);
} catch (final BlockingApiException e) {
throw new EntitlementApiException(e, e.getCode(), e.getMessage());
}
try {
getSubscriptionBase().changePlanWithPolicy(spec, overrides, actionPolicy, callContext);
} catch (final SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
}
final Collection<NotificationEvent> notificationEvents = new ArrayList<NotificationEvent>();
final Iterable<BlockingState> addOnsBlockingStates = computeAddOnBlockingStates(effectiveChangeDate, 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(effectiveChangeDate, notificationEvent, context);
}
return entitlementApi.getEntitlementForId(getId(), callContext);
}
};
return pluginExecution.executeWithPlugin(changePlanWithPlugin, pluginContext);
}
use of org.killbill.notificationq.api.NotificationEvent in project killbill by killbill.
the class DefaultEntitlementService method initialize.
@LifecycleHandlerType(LifecycleLevel.INIT_SERVICE)
public void initialize() {
try {
final NotificationQueueHandler queueHandler = new NotificationQueueHandler() {
@Override
public void handleReadyNotification(final NotificationEvent inputKey, final DateTime eventDateTime, final UUID fromNotificationQueueUserToken, final Long accountRecordId, final Long tenantRecordId) {
final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(tenantRecordId, accountRecordId, "EntitlementQueue", CallOrigin.INTERNAL, UserType.SYSTEM, fromNotificationQueueUserToken);
if (inputKey instanceof EntitlementNotificationKey) {
final CallContext callContext = internalCallContextFactory.createCallContext(internalCallContext);
processEntitlementNotification((EntitlementNotificationKey) inputKey, internalCallContext, callContext);
} else if (inputKey instanceof BlockingTransitionNotificationKey) {
processBlockingNotification((BlockingTransitionNotificationKey) inputKey, internalCallContext);
} else if (inputKey != null) {
log.error("Entitlement service received an unexpected event className='{}", inputKey.getClass());
} else {
log.error("Entitlement service received an unexpected null event");
}
}
};
entitlementEventQueue = notificationQueueService.createNotificationQueue(ENTITLEMENT_SERVICE_NAME, NOTIFICATION_QUEUE_NAME, queueHandler);
} catch (final NotificationQueueAlreadyExists e) {
throw new RuntimeException(e);
}
}
use of org.killbill.notificationq.api.NotificationEvent in project killbill by killbill.
the class DefaultEntitlementInternalApi method cancel.
@Override
public void cancel(final Iterable<Entitlement> entitlements, @Nullable final LocalDate effectiveDate, final BillingActionPolicy billingPolicy, final Iterable<PluginProperty> properties, final InternalCallContext internalCallContext) throws EntitlementApiException {
if (!entitlements.iterator().hasNext()) {
return;
}
int bcd = 0;
DateTimeZone accountTimeZone = null;
try {
bcd = accountApi.getBCD(entitlements.iterator().next().getAccountId(), internalCallContext);
accountTimeZone = accountApi.getImmutableAccountDataByRecordId(internalCallContext.getAccountRecordId(), internalCallContext).getTimeZone();
} catch (final AccountApiException e) {
throw new EntitlementApiException(e);
}
Preconditions.checkState(bcd > 0 && accountTimeZone != null, "Unexpected condition where account info could not be retrieved");
final CallContext callContext = internalCallContextFactory.createCallContext(internalCallContext);
final ImmutableMap.Builder<BlockingState, Optional<UUID>> blockingStates = new ImmutableMap.Builder<BlockingState, Optional<UUID>>();
final Map<DateTime, Collection<NotificationEvent>> notificationEvents = new HashMap<DateTime, Collection<NotificationEvent>>();
final Collection<EntitlementContext> pluginContexts = new LinkedList<EntitlementContext>();
final List<WithEntitlementPlugin> callbacks = new LinkedList<WithEntitlementPlugin>();
final List<SubscriptionBase> subscriptions = new LinkedList<SubscriptionBase>();
for (final Entitlement entitlement : entitlements) {
if (entitlement.getState() == EntitlementState.CANCELLED) {
// If subscription has already been cancelled, we ignore and carry on
continue;
}
final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(entitlement.getBundleId(), entitlement.getExternalKey(), null, effectiveDate, null, false);
final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementWithAddOnsSpecifier);
final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CANCEL_SUBSCRIPTION, entitlement.getAccountId(), null, baseEntitlementWithAddOnsSpecifierList, billingPolicy, properties, callContext);
pluginContexts.add(pluginContext);
final WithEntitlementPlugin<Entitlement> cancelEntitlementWithPlugin = new WithDateOverrideBillingPolicyEntitlementCanceler((DefaultEntitlement) entitlement, blockingStates, notificationEvents, callContext, internalCallContext);
callbacks.add(cancelEntitlementWithPlugin);
subscriptions.add(((DefaultEntitlement) entitlement).getSubscriptionBase());
}
final Callable<Void> preCallbacksCallback = new BulkSubscriptionBaseCancellation(subscriptions, billingPolicy, accountTimeZone, bcd, internalCallContext);
pluginExecution.executeWithPlugin(preCallbacksCallback, callbacks, pluginContexts);
// Record the new states first, then insert the notifications to avoid race conditions
blockingStateDao.setBlockingStatesAndPostBlockingTransitionEvent(blockingStates.build(), internalCallContext);
for (final DateTime effectiveDateForNotification : notificationEvents.keySet()) {
for (final NotificationEvent notificationEvent : notificationEvents.get(effectiveDateForNotification)) {
recordFutureNotification(effectiveDateForNotification, notificationEvent, internalCallContext);
}
}
}
Aggregations