Search in sources :

Example 76 with InternalCallContext

use of org.killbill.billing.callcontext.InternalCallContext 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);
}
Also used : WithEntitlementPlugin(org.killbill.billing.entitlement.api.EntitlementPluginExecution.WithEntitlementPlugin) ArrayList(java.util.ArrayList) NotificationEvent(org.killbill.notificationq.api.NotificationEvent) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) DateTime(org.joda.time.DateTime) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) EntitlementLoggingHelper.logCancelEntitlement(org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logCancelEntitlement) EntitlementLoggingHelper.logUncancelEntitlement(org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logUncancelEntitlement) EntitlementContext(org.killbill.billing.entitlement.plugin.api.EntitlementContext) SubscriptionBaseApiException(org.killbill.billing.subscription.api.user.SubscriptionBaseApiException) PlanPhasePriceOverride(org.killbill.billing.catalog.api.PlanPhasePriceOverride)

Example 77 with InternalCallContext

use of org.killbill.billing.callcontext.InternalCallContext in project killbill by killbill.

the class DefaultEntitlementApi method addEntitlement.

@Override
public Entitlement addEntitlement(final UUID bundleId, final PlanPhaseSpecifier planPhaseSpecifier, final List<PlanPhasePriceOverride> overrides, @Nullable final LocalDate entitlementEffectiveDate, @Nullable final LocalDate billingEffectiveDate, final boolean isMigrated, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
    logCreateEntitlement(log, bundleId, planPhaseSpecifier, overrides, entitlementEffectiveDate, billingEffectiveDate);
    final EntitlementSpecifier entitlementSpecifier = new DefaultEntitlementSpecifier(planPhaseSpecifier, overrides);
    final List<EntitlementSpecifier> entitlementSpecifierList = new ArrayList<EntitlementSpecifier>();
    entitlementSpecifierList.add(entitlementSpecifier);
    final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(bundleId, null, entitlementSpecifierList, entitlementEffectiveDate, billingEffectiveDate, isMigrated);
    final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
    baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementWithAddOnsSpecifier);
    final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CREATE_SUBSCRIPTION, null, null, baseEntitlementWithAddOnsSpecifierList, null, properties, callContext);
    final WithEntitlementPlugin<Entitlement> addEntitlementWithPlugin = new WithEntitlementPlugin<Entitlement>() {

        @Override
        public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
            final EventsStream eventsStreamForBaseSubscription = eventsStreamBuilder.buildForBaseSubscription(bundleId, callContext);
            if (eventsStreamForBaseSubscription.isEntitlementCancelled() || (eventsStreamForBaseSubscription.isEntitlementPending() && (baseEntitlementWithAddOnsSpecifier.getEntitlementEffectiveDate() == null || baseEntitlementWithAddOnsSpecifier.getEntitlementEffectiveDate().compareTo(eventsStreamForBaseSubscription.getEntitlementEffectiveStartDate()) < 0))) {
                throw new EntitlementApiException(ErrorCode.SUB_GET_NO_SUCH_BASE_SUBSCRIPTION, bundleId);
            }
            // Check the base entitlement state is not blocked
            if (eventsStreamForBaseSubscription.isBlockChange()) {
                throw new EntitlementApiException(new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, BlockingChecker.ACTION_CHANGE, BlockingChecker.TYPE_SUBSCRIPTION, eventsStreamForBaseSubscription.getEntitlementId().toString()));
            }
            try {
                final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = getFirstBaseEntitlementWithAddOnsSpecifier(updatedPluginContext.getBaseEntitlementWithAddOnsSpecifiers());
                final EntitlementSpecifier specifier = getFirstEntitlementSpecifier(baseEntitlementWithAddOnsSpecifier);
                final InternalCallContext context = internalCallContextFactory.createInternalCallContext(eventsStreamForBaseSubscription.getAccountId(), callContext);
                final DateTime billingRequestedDate = dateHelper.fromLocalDateAndReferenceTime(baseEntitlementWithAddOnsSpecifier.getBillingEffectiveDate(), context);
                final SubscriptionBase subscription = subscriptionBaseInternalApi.createSubscription(bundleId, specifier.getPlanPhaseSpecifier(), specifier.getOverrides(), billingRequestedDate, isMigrated, context);
                final DateTime entitlementRequestedDate = dateHelper.fromLocalDateAndReferenceTime(baseEntitlementWithAddOnsSpecifier.getEntitlementEffectiveDate(), context);
                final BlockingState newBlockingState = new DefaultBlockingState(subscription.getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_START, EntitlementService.ENTITLEMENT_SERVICE_NAME, false, false, false, entitlementRequestedDate);
                entitlementUtils.setBlockingStatesAndPostBlockingTransitionEvent(ImmutableList.<BlockingState>of(newBlockingState), subscription.getBundleId(), context);
                return new DefaultEntitlement(eventsStreamForBaseSubscription.getAccountId(), subscription.getId(), eventsStreamBuilder, entitlementApi, pluginExecution, blockingStateDao, subscriptionBaseInternalApi, checker, notificationQueueService, entitlementUtils, dateHelper, clock, securityApi, internalCallContextFactory, callContext);
            } catch (final SubscriptionBaseApiException e) {
                throw new EntitlementApiException(e);
            }
        }
    };
    return pluginExecution.executeWithPlugin(addEntitlementWithPlugin, pluginContext);
}
Also used : WithEntitlementPlugin(org.killbill.billing.entitlement.api.EntitlementPluginExecution.WithEntitlementPlugin) EventsStream(org.killbill.billing.entitlement.EventsStream) ArrayList(java.util.ArrayList) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) DateTime(org.joda.time.DateTime) SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) EntitlementLoggingHelper.logPauseResumeEntitlement(org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logPauseResumeEntitlement) EntitlementLoggingHelper.logTransferEntitlement(org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logTransferEntitlement) EntitlementLoggingHelper.logCreateEntitlement(org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logCreateEntitlement) EntitlementContext(org.killbill.billing.entitlement.plugin.api.EntitlementContext) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) SubscriptionBaseApiException(org.killbill.billing.subscription.api.user.SubscriptionBaseApiException) PlanPhasePriceOverride(org.killbill.billing.catalog.api.PlanPhasePriceOverride)

Example 78 with InternalCallContext

use of org.killbill.billing.callcontext.InternalCallContext in project killbill by killbill.

the class DefaultEntitlementApi method transferEntitlementsOverrideBillingPolicy.

@Override
public UUID transferEntitlementsOverrideBillingPolicy(final UUID sourceAccountId, final UUID destAccountId, final String externalKey, @Nullable final LocalDate effectiveDate, final BillingActionPolicy billingPolicy, final Iterable<PluginProperty> properties, final CallContext context) throws EntitlementApiException {
    logTransferEntitlement(log, sourceAccountId, destAccountId, externalKey, effectiveDate, billingPolicy);
    final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(null, externalKey, 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 EntitlementContext 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(externalKey, contextWithSourceAccountRecordId);
                final SubscriptionBase baseSubscription = activeSubscriptionIdForKey != null ? subscriptionBaseInternalApi.getSubscriptionFromId(activeSubscriptionIdForKey, contextWithSourceAccountRecordId) : null;
                final SubscriptionBaseBundle baseBundle = baseSubscription != null ? subscriptionBaseInternalApi.getBundleFromId(baseSubscription.getBundleId(), contextWithSourceAccountRecordId) : null;
                if (baseBundle == null || !baseBundle.getAccountId().equals(sourceAccountId)) {
                    throw new EntitlementApiException(new SubscriptionBaseApiException(ErrorCode.SUB_GET_INVALID_BUNDLE_KEY, externalKey));
                }
                final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = getFirstBaseEntitlementWithAddOnsSpecifier(updatedPluginContext.getBaseEntitlementWithAddOnsSpecifiers());
                final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(baseEntitlementWithAddOnsSpecifier.getBillingEffectiveDate(), contextWithSourceAccountRecordId);
                final SubscriptionBaseBundle newBundle = subscriptionBaseTransferApi.transferBundle(sourceAccountId, destAccountId, externalKey, requestedDate, true, cancelImm, context);
                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(baseBundle.getId(), null, contextWithSourceAccountRecordId)) {
                    final BlockingState blockingState = new DefaultBlockingState(subscriptionBase.getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_CANCELLED, EntitlementService.ENTITLEMENT_SERVICE_NAME, 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(), contextWithDestAccountRecordId);
                for (final SubscriptionBase subscriptionBase : subscriptionBaseInternalApi.getSubscriptionsForBundle(newBundle.getId(), null, contextWithDestAccountRecordId)) {
                    final BlockingState newBlockingState = new DefaultBlockingState(subscriptionBase.getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_START, EntitlementService.ENTITLEMENT_SERVICE_NAME, 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);
}
Also used : WithEntitlementPlugin(org.killbill.billing.entitlement.api.EntitlementPluginExecution.WithEntitlementPlugin) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) DateTime(org.joda.time.DateTime) SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) SubscriptionBaseBundle(org.killbill.billing.subscription.api.user.SubscriptionBaseBundle) UUID(java.util.UUID) EntitlementContext(org.killbill.billing.entitlement.plugin.api.EntitlementContext) SubscriptionBaseApiException(org.killbill.billing.subscription.api.user.SubscriptionBaseApiException) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) SubscriptionBaseTransferApiException(org.killbill.billing.subscription.api.transfer.SubscriptionBaseTransferApiException) PlanPhasePriceOverride(org.killbill.billing.catalog.api.PlanPhasePriceOverride)

Example 79 with InternalCallContext

use of org.killbill.billing.callcontext.InternalCallContext in project killbill by killbill.

the class DefaultEntitlementApi method resume.

@Override
public void resume(final UUID bundleId, final LocalDate localEffectiveDate, final Iterable<PluginProperty> properties, final CallContext context) throws EntitlementApiException {
    logPauseResumeEntitlement(log, "Resume", bundleId, localEffectiveDate);
    final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(bundleId, ObjectType.BUNDLE, context);
    super.resume(bundleId, localEffectiveDate, properties, contextWithValidAccountRecordId);
}
Also used : InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) PlanPhasePriceOverride(org.killbill.billing.catalog.api.PlanPhasePriceOverride)

Example 80 with InternalCallContext

use of org.killbill.billing.callcontext.InternalCallContext 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);
    }
}
Also used : EntitlementNotificationKey(org.killbill.billing.entitlement.engine.core.EntitlementNotificationKey) BlockingTransitionNotificationKey(org.killbill.billing.entitlement.engine.core.BlockingTransitionNotificationKey) NotificationEvent(org.killbill.notificationq.api.NotificationEvent) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) UUID(java.util.UUID) NotificationQueueAlreadyExists(org.killbill.notificationq.api.NotificationQueueService.NotificationQueueAlreadyExists) NotificationQueueHandler(org.killbill.notificationq.api.NotificationQueueService.NotificationQueueHandler) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) CallContext(org.killbill.billing.util.callcontext.CallContext) DateTime(org.joda.time.DateTime) LifecycleHandlerType(org.killbill.billing.platform.api.LifecycleHandlerType)

Aggregations

InternalCallContext (org.killbill.billing.callcontext.InternalCallContext)110 PlanPhasePriceOverride (org.killbill.billing.catalog.api.PlanPhasePriceOverride)26 DateTime (org.joda.time.DateTime)25 UUID (java.util.UUID)24 ArrayList (java.util.ArrayList)21 SubscriptionBaseApiException (org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)17 InvoiceApiException (org.killbill.billing.invoice.api.InvoiceApiException)14 CallContext (org.killbill.billing.util.callcontext.CallContext)14 CatalogApiException (org.killbill.billing.catalog.api.CatalogApiException)13 WithEntitlementPlugin (org.killbill.billing.entitlement.api.EntitlementPluginExecution.WithEntitlementPlugin)13 EntitlementContext (org.killbill.billing.entitlement.plugin.api.EntitlementContext)13 AccountApiException (org.killbill.billing.account.api.AccountApiException)12 DefaultBlockingState (org.killbill.billing.junction.DefaultBlockingState)12 NotificationEvent (org.killbill.notificationq.api.NotificationEvent)9 BigDecimal (java.math.BigDecimal)8 LinkedList (java.util.LinkedList)8 InternalTenantContext (org.killbill.billing.callcontext.InternalTenantContext)8 Invoice (org.killbill.billing.invoice.api.Invoice)8 AllowConcurrentEvents (com.google.common.eventbus.AllowConcurrentEvents)7 Subscribe (com.google.common.eventbus.Subscribe)7