Search in sources :

Example 1 with NotificationEvent

use of org.killbill.notificationq.api.NotificationEvent in project killbill by killbill.

the class BaseRetryService method initialize.

@Override
public void initialize() throws NotificationQueueAlreadyExists {
    retryQueue = notificationQueueService.createNotificationQueue(DefaultPaymentService.SERVICE_NAME, getQueueName(), new NotificationQueueHandler() {

        @Override
        public void handleReadyNotification(final NotificationEvent notificationKey, final DateTime eventDateTime, final UUID userToken, final Long accountRecordId, final Long tenantRecordId) {
            if (!(notificationKey instanceof PaymentRetryNotificationKey)) {
                log.error("Payment service got an unexpected notification type {}", notificationKey.getClass().getName());
                return;
            }
            final PaymentRetryNotificationKey key = (PaymentRetryNotificationKey) notificationKey;
            final InternalCallContext callContext = internalCallContextFactory.createInternalCallContext(tenantRecordId, accountRecordId, paymentRetryService, CallOrigin.INTERNAL, UserType.SYSTEM, userToken);
            retryPaymentTransaction(key.getAttemptId(), key.getPaymentControlPluginNames(), callContext);
        }
    });
}
Also used : NotificationEvent(org.killbill.notificationq.api.NotificationEvent) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) UUID(java.util.UUID) NotificationQueueHandler(org.killbill.notificationq.api.NotificationQueueService.NotificationQueueHandler) DateTime(org.joda.time.DateTime)

Example 2 with NotificationEvent

use of org.killbill.notificationq.api.NotificationEvent in project killbill by killbill.

the class PaymentProcessor method getPaymentAttempts.

private List<PaymentAttempt> getPaymentAttempts(final List<PaymentAttemptModelDao> pastPaymentAttempts, final InternalTenantContext internalTenantContext) {
    List<PaymentAttempt> paymentAttempts = new ArrayList<PaymentAttempt>();
    // Add Past Payment Attempts
    for (PaymentAttemptModelDao pastPaymentAttempt : pastPaymentAttempts) {
        DefaultPaymentAttempt paymentAttempt = new DefaultPaymentAttempt(pastPaymentAttempt.getAccountId(), pastPaymentAttempt.getPaymentMethodId(), pastPaymentAttempt.getId(), pastPaymentAttempt.getCreatedDate(), pastPaymentAttempt.getUpdatedDate(), pastPaymentAttempt.getCreatedDate(), pastPaymentAttempt.getPaymentExternalKey(), pastPaymentAttempt.getTransactionId(), pastPaymentAttempt.getTransactionExternalKey(), pastPaymentAttempt.getTransactionType(), pastPaymentAttempt.getStateName(), pastPaymentAttempt.getAmount(), pastPaymentAttempt.getCurrency(), pastPaymentAttempt.getPluginName(), buildPluginProperties(pastPaymentAttempt));
        paymentAttempts.add(paymentAttempt);
    }
    // Get Future Payment Attempts from Notification Queue and add them to the list
    try {
        final NotificationQueue retryQueue = notificationQueueService.getNotificationQueue(DefaultPaymentService.SERVICE_NAME, DefaultRetryService.QUEUE_NAME);
        final Iterable<NotificationEventWithMetadata<NotificationEvent>> notificationEventWithMetadatas = retryQueue.getFutureNotificationForSearchKeys(internalTenantContext.getAccountRecordId(), internalTenantContext.getTenantRecordId());
        for (final NotificationEventWithMetadata<NotificationEvent> notificationEvent : notificationEventWithMetadatas) {
            // Last Attempt
            PaymentAttemptModelDao lastPaymentAttempt = getLastPaymentAttempt(pastPaymentAttempts, ((PaymentRetryNotificationKey) notificationEvent.getEvent()).getAttemptId());
            if (lastPaymentAttempt != null) {
                DefaultPaymentAttempt futurePaymentAttempt = new DefaultPaymentAttempt(// accountId
                lastPaymentAttempt.getAccountId(), // paymentMethodId
                lastPaymentAttempt.getPaymentMethodId(), // id
                ((PaymentRetryNotificationKey) notificationEvent.getEvent()).getAttemptId(), // createdDate
                null, // updatedDate
                null, // effectiveDate
                notificationEvent.getEffectiveDate(), // paymentExternalKey
                lastPaymentAttempt.getPaymentExternalKey(), // transactionId
                null, // transactionExternalKey
                lastPaymentAttempt.getTransactionExternalKey(), // transactionType
                lastPaymentAttempt.getTransactionType(), // stateName
                SCHEDULED, // amount
                lastPaymentAttempt.getAmount(), // currency
                lastPaymentAttempt.getCurrency(), // pluginName,
                ((PaymentRetryNotificationKey) notificationEvent.getEvent()).getPaymentControlPluginNames().get(0), // pluginProperties
                buildPluginProperties(lastPaymentAttempt));
                paymentAttempts.add(futurePaymentAttempt);
            }
        }
    } catch (NoSuchNotificationQueue noSuchNotificationQueue) {
        log.error("ERROR Loading Notification Queue - " + noSuchNotificationQueue.getMessage());
    }
    return paymentAttempts;
}
Also used : PaymentAttemptModelDao(org.killbill.billing.payment.dao.PaymentAttemptModelDao) NoSuchNotificationQueue(org.killbill.notificationq.api.NotificationQueueService.NoSuchNotificationQueue) DefaultPaymentAttempt(org.killbill.billing.payment.api.DefaultPaymentAttempt) ArrayList(java.util.ArrayList) PaymentRetryNotificationKey(org.killbill.billing.payment.retry.PaymentRetryNotificationKey) DefaultPaymentAttempt(org.killbill.billing.payment.api.DefaultPaymentAttempt) PaymentAttempt(org.killbill.billing.payment.api.PaymentAttempt) NotificationEventWithMetadata(org.killbill.notificationq.api.NotificationEventWithMetadata) NotificationEvent(org.killbill.notificationq.api.NotificationEvent) NotificationQueue(org.killbill.notificationq.api.NotificationQueue) NoSuchNotificationQueue(org.killbill.notificationq.api.NotificationQueueService.NoSuchNotificationQueue)

Example 3 with NotificationEvent

use of org.killbill.notificationq.api.NotificationEvent in project killbill by killbill.

the class DefaultEntitlement method cancelEntitlementWithDate.

@Override
public Entitlement cancelEntitlementWithDate(@Nullable final LocalDate entitlementEffectiveDate, final boolean overrideBillingEffectiveDate, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
    logCancelEntitlement(log, this, entitlementEffectiveDate, overrideBillingEffectiveDate, null, null);
    checkForPermissions(Permission.ENTITLEMENT_CAN_CANCEL, callContext);
    // Get the latest state from disk
    refresh(callContext);
    if (entitlementEffectiveDate != null && entitlementEffectiveDate.compareTo(getEffectiveStartDate()) < 0) {
        throw new EntitlementApiException(ErrorCode.SUB_INVALID_REQUESTED_DATE, entitlementEffectiveDate, getEffectiveStartDate());
    }
    final LocalDate billingEffectiveDate = overrideBillingEffectiveDate ? entitlementEffectiveDate : null;
    final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(getBundleId(), getExternalKey(), null, entitlementEffectiveDate, billingEffectiveDate, false);
    final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
    baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementWithAddOnsSpecifier);
    final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CANCEL_SUBSCRIPTION, getAccountId(), null, baseEntitlementWithAddOnsSpecifierList, null, 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);
            final DateTime effectiveCancelDate = dateHelper.fromLocalDateAndReferenceTimeWithMinimum(entitlementEffectiveDate, getEventsStream().getEntitlementEffectiveStartDateTime(), contextWithValidAccountRecordId);
            try {
                if (overrideBillingEffectiveDate) {
                    getSubscriptionBase().cancelWithDate(effectiveCancelDate, callContext);
                } else {
                    getSubscriptionBase().cancel(callContext);
                }
            } catch (final SubscriptionBaseApiException e) {
                throw new EntitlementApiException(e);
            }
            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);
}
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) LocalDate(org.joda.time.LocalDate) DateTime(org.joda.time.DateTime) 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) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) PlanPhasePriceOverride(org.killbill.billing.catalog.api.PlanPhasePriceOverride)

Example 4 with NotificationEvent

use of org.killbill.notificationq.api.NotificationEvent in project killbill by killbill.

the class DefaultEntitlement method changePlan.

@Override
public Entitlement changePlan(final PlanSpecifier spec, final List<PlanPhasePriceOverride> overrides, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
    logChangePlan(log, this, spec, overrides, null, null);
    checkForPermissions(Permission.ENTITLEMENT_CAN_CHANGE_PLAN, callContext);
    // Get the latest state from disk
    refresh(callContext);
    final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(getBundleId(), getExternalKey(), 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, 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;
            try {
                effectiveChangeDate = subscriptionInternalApi.getDryRunChangePlanEffectiveDate(getSubscriptionBase(), spec, null, 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(), effectiveChangeDate, context);
            } catch (final BlockingApiException e) {
                throw new EntitlementApiException(e, e.getCode(), e.getMessage());
            }
            try {
                getSubscriptionBase().changePlan(spec, overrides, 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 5 with NotificationEvent

use of org.killbill.notificationq.api.NotificationEvent in project killbill by killbill.

the class DefaultEntitlement method computeAddOnBlockingStates.

public Collection<BlockingState> computeAddOnBlockingStates(final DateTime effectiveDate, final Collection<NotificationEvent> notificationEvents, final TenantContext context, final InternalCallContext internalCallContext) throws EntitlementApiException {
    // Optimization - bail early
    if (!ProductCategory.BASE.equals(getSubscriptionBase().getCategory())) {
        // Only base subscriptions have add-ons
        return ImmutableList.<BlockingState>of();
    }
    // Get the latest state from disk (we just got cancelled or changed plan)
    refresh(context);
    // If cancellation/change occurs in the future, do nothing for now but add a notification entry.
    // This is to distinguish whether a future cancellation was requested by the user, or was a side effect
    // (e.g. base plan cancellation): future entitlement cancellations for add-ons on disk always reflect
    // an explicit cancellation. This trick lets us determine what to do when un-cancelling.
    // This mirror the behavior in subscription base (see DefaultSubscriptionBaseApiService).
    final DateTime now = clock.getUTCNow();
    if (effectiveDate.compareTo(now) > 0) {
        // Note that usually we record the notification from the DAO. We cannot do it here because not all calls
        // go through the DAO (e.g. change)
        final boolean isBaseEntitlementCancelled = eventsStream.isEntitlementCancelled();
        final NotificationEvent notificationEvent = new EntitlementNotificationKey(getId(), getBundleId(), isBaseEntitlementCancelled ? EntitlementNotificationKeyAction.CANCEL : EntitlementNotificationKeyAction.CHANGE, effectiveDate);
        notificationEvents.add(notificationEvent);
        return ImmutableList.<BlockingState>of();
    }
    return eventsStream.computeAddonsBlockingStatesForNextSubscriptionBaseEvent(effectiveDate);
}
Also used : EntitlementNotificationKey(org.killbill.billing.entitlement.engine.core.EntitlementNotificationKey) NotificationEvent(org.killbill.notificationq.api.NotificationEvent) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) DateTime(org.joda.time.DateTime)

Aggregations

NotificationEvent (org.killbill.notificationq.api.NotificationEvent)21 DateTime (org.joda.time.DateTime)16 InternalCallContext (org.killbill.billing.callcontext.InternalCallContext)9 ArrayList (java.util.ArrayList)8 UUID (java.util.UUID)8 DefaultBlockingState (org.killbill.billing.junction.DefaultBlockingState)7 PlanPhasePriceOverride (org.killbill.billing.catalog.api.PlanPhasePriceOverride)6 WithEntitlementPlugin (org.killbill.billing.entitlement.api.EntitlementPluginExecution.WithEntitlementPlugin)6 EntitlementContext (org.killbill.billing.entitlement.plugin.api.EntitlementContext)6 SubscriptionBaseApiException (org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)6 NotificationQueueHandler (org.killbill.notificationq.api.NotificationQueueService.NotificationQueueHandler)6 EntitlementLoggingHelper.logCancelEntitlement (org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logCancelEntitlement)5 EntitlementLoggingHelper.logUncancelEntitlement (org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logUncancelEntitlement)5 NotificationEventWithMetadata (org.killbill.notificationq.api.NotificationEventWithMetadata)5 CatalogApiException (org.killbill.billing.catalog.api.CatalogApiException)3 NotificationQueue (org.killbill.notificationq.api.NotificationQueue)3 BlockingState (org.killbill.billing.entitlement.api.BlockingState)2 BlockingTransitionNotificationKey (org.killbill.billing.entitlement.engine.core.BlockingTransitionNotificationKey)2 EntitlementNotificationKey (org.killbill.billing.entitlement.engine.core.EntitlementNotificationKey)2 LifecycleHandlerType (org.killbill.billing.platform.api.LifecycleHandlerType)2