Search in sources :

Example 11 with SubscriptionBaseApiException

use of org.killbill.billing.subscription.api.user.SubscriptionBaseApiException in project killbill by killbill.

the class InvoiceDispatcher method processAccountWithLock.

private Invoice processAccountWithLock(final boolean parkedAccount, final UUID accountId, @Nullable final LocalDate inputTargetDateMaybeNull, @Nullable final DryRunArguments dryRunArguments, final InternalCallContext context) throws InvoiceApiException {
    final boolean isDryRun = dryRunArguments != null;
    final boolean upcomingInvoiceDryRun = isDryRun && DryRunType.UPCOMING_INVOICE.equals(dryRunArguments.getDryRunType());
    LocalDate inputTargetDate = inputTargetDateMaybeNull;
    // A null inputTargetDate is only allowed in dryRun mode to have the system compute it
    if (inputTargetDate == null && !upcomingInvoiceDryRun) {
        inputTargetDate = clock.getUTCToday();
    }
    Preconditions.checkArgument(inputTargetDate != null || upcomingInvoiceDryRun, "inputTargetDate is required in non dryRun mode");
    try {
        // Make sure to first set the BCD if needed then get the account object (to have the BCD set)
        final BillingEventSet billingEvents = billingApi.getBillingEventsForAccountAndUpdateAccountBCD(accountId, dryRunArguments, context);
        if (billingEvents.isEmpty()) {
            return null;
        }
        final Iterable<UUID> filteredSubscriptionIdsForDryRun = getFilteredSubscriptionIdsForDryRun(dryRunArguments, billingEvents);
        final List<LocalDate> candidateTargetDates = (inputTargetDate != null) ? ImmutableList.<LocalDate>of(inputTargetDate) : getUpcomingInvoiceCandidateDates(filteredSubscriptionIdsForDryRun, context);
        for (final LocalDate curTargetDate : candidateTargetDates) {
            final Invoice invoice = processAccountWithLockAndInputTargetDate(accountId, curTargetDate, billingEvents, isDryRun, context);
            if (invoice != null) {
                filterInvoiceItemsForDryRun(filteredSubscriptionIdsForDryRun, invoice);
                if (!isDryRun && parkedAccount) {
                    try {
                        log.info("Illegal invoicing state fixed for accountId='{}', unparking account", accountId);
                        parkedAccountsManager.unparkAccount(accountId, context);
                    } catch (final TagApiException ignored) {
                        log.warn("Unable to unpark account", ignored);
                    }
                }
                return invoice;
            }
        }
        return null;
    } catch (final CatalogApiException e) {
        log.warn("Failed to retrieve BillingEvents for accountId='{}', dryRunArguments='{}'", accountId, dryRunArguments, e);
        return null;
    } catch (final AccountApiException e) {
        log.warn("Failed to retrieve BillingEvents for accountId='{}', dryRunArguments='{}'", accountId, dryRunArguments, e);
        return null;
    } catch (final SubscriptionBaseApiException e) {
        log.warn("Failed to retrieve BillingEvents for accountId='{}', dryRunArguments='{}'", accountId, dryRunArguments, e);
        return null;
    } catch (final InvoiceApiException e) {
        if (e.getCode() == ErrorCode.UNEXPECTED_ERROR.getCode() && !isDryRun) {
            log.warn("Illegal invoicing state detected for accountId='{}', dryRunArguments='{}', parking account", accountId, dryRunArguments, e);
            parkAccount(accountId, context);
        }
        throw e;
    }
}
Also used : InvoiceApiException(org.killbill.billing.invoice.api.InvoiceApiException) DefaultInvoice(org.killbill.billing.invoice.model.DefaultInvoice) Invoice(org.killbill.billing.invoice.api.Invoice) TagApiException(org.killbill.billing.util.api.TagApiException) BillingEventSet(org.killbill.billing.junction.BillingEventSet) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) AccountApiException(org.killbill.billing.account.api.AccountApiException) UUID(java.util.UUID) LocalDate(org.joda.time.LocalDate) SubscriptionBaseApiException(org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)

Example 12 with SubscriptionBaseApiException

use of org.killbill.billing.subscription.api.user.SubscriptionBaseApiException in project killbill by killbill.

the class InvoiceDispatcher method processAccountInternal.

private Invoice processAccountInternal(final boolean isApiCall, final boolean parkedAccount, final UUID accountId, @Nullable final LocalDate inputTargetDateMaybeNull, @Nullable final DryRunArguments dryRunArguments, final boolean isRescheduled, final InternalCallContext context) throws InvoiceApiException {
    final boolean isDryRun = dryRunArguments != null;
    final boolean upcomingInvoiceDryRun = isDryRun && DryRunType.UPCOMING_INVOICE.equals(dryRunArguments.getDryRunType());
    LocalDate inputTargetDate = inputTargetDateMaybeNull;
    // A null inputTargetDate is only allowed in UPCOMING_INVOICE dryRun mode to have the system compute it
    if (inputTargetDate == null && !upcomingInvoiceDryRun) {
        inputTargetDate = context.toLocalDate(clock.getUTCNow());
    }
    Preconditions.checkArgument(inputTargetDate != null || upcomingInvoiceDryRun, "inputTargetDate is required in non dryRun mode");
    // Passed through invoice code to be propagated to usage module/plugins
    final LocalDate dryRunInfoDate = isDryRun && dryRunArguments.getDryRunType() == DryRunType.SUBSCRIPTION_ACTION ? dryRunArguments.getEffectiveDate() : inputTargetDate;
    final DryRunInfo dryRunInfo = isDryRun ? new DryRunInfo(dryRunArguments.getDryRunType(), dryRunInfoDate) : null;
    final Map<InvoiceTiming, Long> invoiceTimings = new HashMap<>();
    try {
        long startNano = System.nanoTime();
        final AccountInvoices accountInvoices = invoiceOptimizer.getInvoices(context);
        invoiceTimings.put(InvoiceTiming.FETCH_INVOICES, System.nanoTime() - startNano);
        // Make sure to first set the BCD if needed then get the account object (to have the BCD set)
        startNano = System.nanoTime();
        final BillingEventSet billingEvents = billingApi.getBillingEventsForAccountAndUpdateAccountBCD(accountId, dryRunArguments, accountInvoices.getBillingEventCutoffDate(), context);
        invoiceTimings.put(InvoiceTiming.BILLING_EVENTS, System.nanoTime() - startNano);
        if (!isApiCall && billingEvents.isAccountAutoInvoiceOff()) {
            return null;
        }
        final Invoice invoice;
        if (!isDryRun) {
            final InvoiceWithFutureNotifications invoiceWithFutureNotifications = processAccountWithLockAndInputTargetDate(accountId, inputTargetDate, billingEvents, accountInvoices, dryRunInfo, isRescheduled, Lists.newLinkedList(), invoiceTimings, context);
            invoice = invoiceWithFutureNotifications != null ? invoiceWithFutureNotifications.getInvoice() : null;
            if (parkedAccount) {
                try {
                    log.info("Illegal invoicing state fixed for accountId='{}', unparking account", accountId);
                    parkedAccountsManager.unparkAccount(accountId, context);
                } catch (final TagApiException ignored) {
                    log.warn("Unable to unpark account", ignored);
                }
            }
        } else /* Dry run use cases */
        {
            final NotificationQueue notificationQueue = notificationQueueService.getNotificationQueue(KILLBILL_SERVICES.INVOICE_SERVICE.getServiceName(), DefaultNextBillingDateNotifier.NEXT_BILLING_DATE_NOTIFIER_QUEUE);
            final Iterable<NotificationEventWithMetadata<NextBillingDateNotificationKey>> futureNotificationsIterable = notificationQueue.getFutureNotificationForSearchKeys(context.getAccountRecordId(), context.getTenantRecordId());
            // Copy the results as retrieving the iterator will issue a query each time. This also makes sure the underlying JDBC connection is closed.
            final List<NotificationEventWithMetadata<NextBillingDateNotificationKey>> futureNotifications = ImmutableList.<NotificationEventWithMetadata<NextBillingDateNotificationKey>>copyOf(futureNotificationsIterable);
            final Map<UUID, DateTime> nextScheduledSubscriptionsEventMap = getNextTransitionsForSubscriptions(billingEvents);
            // List of all existing invoice notifications
            final Set<LocalDate> allCandidateTargetDates = getUpcomingInvoiceCandidateDates(futureNotifications, nextScheduledSubscriptionsEventMap, ImmutableList.<UUID>of(), context);
            if (dryRunArguments.getDryRunType() == DryRunType.UPCOMING_INVOICE) {
                final Iterable<UUID> filteredSubscriptionIdsForDryRun = getFilteredSubscriptionIdsFor_UPCOMING_INVOICE_DryRun(dryRunArguments, billingEvents);
                // List of existing invoice notifications associated to the filter set of subscriptionIds
                final Set<LocalDate> filteredCandidateTargetDates = Iterables.isEmpty(filteredSubscriptionIdsForDryRun) ? allCandidateTargetDates : getUpcomingInvoiceCandidateDates(futureNotifications, nextScheduledSubscriptionsEventMap, filteredSubscriptionIdsForDryRun, context);
                if (Iterables.isEmpty(filteredSubscriptionIdsForDryRun)) {
                    invoice = processDryRun_UPCOMING_INVOICE_Invoice(accountId, allCandidateTargetDates, billingEvents, accountInvoices, dryRunInfo, invoiceTimings, context);
                } else {
                    invoice = processDryRun_UPCOMING_INVOICE_FILTERING_Invoice(accountId, filteredCandidateTargetDates, allCandidateTargetDates, billingEvents, accountInvoices, dryRunInfo, invoiceTimings, context);
                }
            } else /* DryRunType.TARGET_DATE, SUBSCRIPTION_ACTION */
            {
                invoice = processDryRun_TARGET_DATE_Invoice(accountId, inputTargetDate, allCandidateTargetDates, billingEvents, accountInvoices, dryRunInfo, invoiceTimings, context);
            }
        }
        printInvoiceTiming(invoiceTimings);
        return invoice;
    } catch (final CatalogApiException e) {
        log.warn("Failed to retrieve BillingEvents for accountId='{}', dryRunArguments='{}'", accountId, dryRunArguments, e);
        return null;
    } catch (final AccountApiException e) {
        log.warn("Failed to retrieve BillingEvents for accountId='{}', dryRunArguments='{}'", accountId, dryRunArguments, e);
        return null;
    } catch (final SubscriptionBaseApiException e) {
        log.warn("Failed to retrieve BillingEvents for accountId='{}', dryRunArguments='{}'", accountId, dryRunArguments, e);
        return null;
    } catch (final InvoiceApiException e) {
        if (e.getCode() == ErrorCode.INVOICE_PLUGIN_API_ABORTED.getCode()) {
            return null;
        }
        if (e.getCode() == ErrorCode.UNEXPECTED_ERROR.getCode() && !isDryRun) {
            log.warn("Illegal invoicing state detected for accountId='{}', dryRunArguments='{}', parking account", accountId, dryRunArguments, e);
            parkAccount(accountId, context);
        }
        throw e;
    } catch (final NoSuchNotificationQueue e) {
        throw new InvoiceApiException(ErrorCode.UNEXPECTED_ERROR, "Failed to retrieve future notifications from notificationQ");
    }
}
Also used : AccountInvoices(org.killbill.billing.invoice.optimizer.InvoiceOptimizerBase.AccountInvoices) DefaultInvoice(org.killbill.billing.invoice.model.DefaultInvoice) Invoice(org.killbill.billing.invoice.api.Invoice) HashMap(java.util.HashMap) NotificationQueue(org.killbill.notificationq.api.NotificationQueue) NoSuchNotificationQueue(org.killbill.notificationq.api.NotificationQueueService.NoSuchNotificationQueue) LocalDate(org.joda.time.LocalDate) DryRunInfo(org.killbill.billing.invoice.api.DryRunInfo) DateTime(org.joda.time.DateTime) InvoiceApiException(org.killbill.billing.invoice.api.InvoiceApiException) AccountApiException(org.killbill.billing.account.api.AccountApiException) NotificationEventWithMetadata(org.killbill.notificationq.api.NotificationEventWithMetadata) UUID(java.util.UUID) SubscriptionBaseApiException(org.killbill.billing.subscription.api.user.SubscriptionBaseApiException) NoSuchNotificationQueue(org.killbill.notificationq.api.NotificationQueueService.NoSuchNotificationQueue) TagApiException(org.killbill.billing.util.api.TagApiException) BillingEventSet(org.killbill.billing.junction.BillingEventSet) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException)

Example 13 with SubscriptionBaseApiException

use of org.killbill.billing.subscription.api.user.SubscriptionBaseApiException in project killbill by killbill.

the class InvoiceDispatcher method processSubscriptionStartRequestedDateWithLock.

private void processSubscriptionStartRequestedDateWithLock(final UUID accountId, final RequestedSubscriptionInternalEvent transition, final InternalCallContext context) {
    try {
        // TODO
        // Can we use cutoffDt ?
        // Do we even need the billing events ?
        final BillingEventSet billingEvents = billingApi.getBillingEventsForAccountAndUpdateAccountBCD(accountId, null, null, context);
        if (billingEvents.isEmpty()) {
            return;
        }
        final FutureAccountNotificationsBuilder notificationsBuilder = new FutureAccountNotificationsBuilder();
        populateNextFutureDryRunNotificationDate(billingEvents, notificationsBuilder, context);
        final ImmutableAccountData account = accountApi.getImmutableAccountDataById(accountId, context);
        setFutureNotifications(account, notificationsBuilder.build(), context);
    } catch (final SubscriptionBaseApiException e) {
        log.warn("Failed handling SubscriptionBase change.", new InvoiceApiException(ErrorCode.INVOICE_NO_ACCOUNT_ID_FOR_SUBSCRIPTION_ID, transition.getSubscriptionId().toString()));
    } catch (final AccountApiException e) {
        log.warn("Failed to retrieve BillingEvents for accountId='{}'", accountId, e);
    } catch (final CatalogApiException e) {
        log.warn("Failed to retrieve BillingEvents for accountId='{}'", accountId, e);
    }
}
Also used : ImmutableAccountData(org.killbill.billing.account.api.ImmutableAccountData) InvoiceApiException(org.killbill.billing.invoice.api.InvoiceApiException) BillingEventSet(org.killbill.billing.junction.BillingEventSet) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) AccountApiException(org.killbill.billing.account.api.AccountApiException) FutureAccountNotificationsBuilder(org.killbill.billing.invoice.InvoiceDispatcher.FutureAccountNotifications.FutureAccountNotificationsBuilder) SubscriptionBaseApiException(org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)

Example 14 with SubscriptionBaseApiException

use of org.killbill.billing.subscription.api.user.SubscriptionBaseApiException in project killbill by killbill.

the class EventsStreamBuilder method buildForBundle.

public List<EventsStream> buildForBundle(final UUID bundleId, final InternalTenantContext internalTenantContext) throws EntitlementApiException {
    final SubscriptionBaseBundle bundle;
    final List<SubscriptionBase> subscriptionsForBundle;
    try {
        bundle = subscriptionInternalApi.getBundleFromId(bundleId, internalTenantContext);
        subscriptionsForBundle = subscriptionInternalApi.getSubscriptionsForBundle(bundleId, null, internalTenantContext);
    } catch (final SubscriptionBaseApiException e) {
        throw new EntitlementApiException(e);
    }
    final List<EventsStream> eventsStreams = new LinkedList<EventsStream>();
    for (final SubscriptionBase subscription : subscriptionsForBundle) {
        eventsStreams.add(buildForEntitlement(bundle, subscription, subscriptionsForBundle, internalTenantContext));
    }
    return eventsStreams;
}
Also used : SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) EventsStream(org.killbill.billing.entitlement.EventsStream) SubscriptionBaseBundle(org.killbill.billing.subscription.api.user.SubscriptionBaseBundle) EntitlementApiException(org.killbill.billing.entitlement.api.EntitlementApiException) SubscriptionBaseApiException(org.killbill.billing.subscription.api.user.SubscriptionBaseApiException) LinkedList(java.util.LinkedList)

Example 15 with SubscriptionBaseApiException

use of org.killbill.billing.subscription.api.user.SubscriptionBaseApiException in project killbill by killbill.

the class EventsStreamBuilder method buildForBaseSubscription.

public EventsStream buildForBaseSubscription(final UUID bundleId, final TenantContext tenantContext) throws EntitlementApiException {
    final SubscriptionBase baseSubscription;
    try {
        final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(bundleId, ObjectType.BUNDLE, tenantContext);
        baseSubscription = subscriptionInternalApi.getBaseSubscription(bundleId, internalTenantContext);
    } catch (final SubscriptionBaseApiException e) {
        throw new EntitlementApiException(e);
    }
    return buildForEntitlement(baseSubscription.getId(), tenantContext);
}
Also used : SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) InternalTenantContext(org.killbill.billing.callcontext.InternalTenantContext) EntitlementApiException(org.killbill.billing.entitlement.api.EntitlementApiException) SubscriptionBaseApiException(org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)

Aggregations

SubscriptionBaseApiException (org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)72 ArrayList (java.util.ArrayList)29 DateTime (org.joda.time.DateTime)29 CatalogApiException (org.killbill.billing.catalog.api.CatalogApiException)28 UUID (java.util.UUID)27 InternalCallContext (org.killbill.billing.callcontext.InternalCallContext)24 SubscriptionBase (org.killbill.billing.subscription.api.SubscriptionBase)24 WithEntitlementPlugin (org.killbill.billing.entitlement.api.EntitlementPluginExecution.WithEntitlementPlugin)19 EntitlementContext (org.killbill.billing.entitlement.plugin.api.EntitlementContext)19 DefaultSubscriptionBase (org.killbill.billing.subscription.api.user.DefaultSubscriptionBase)17 SubscriptionBaseBundle (org.killbill.billing.subscription.api.user.SubscriptionBaseBundle)16 PlanPhasePriceOverride (org.killbill.billing.catalog.api.PlanPhasePriceOverride)14 DefaultBlockingState (org.killbill.billing.junction.DefaultBlockingState)14 InternalTenantContext (org.killbill.billing.callcontext.InternalTenantContext)11 Plan (org.killbill.billing.catalog.api.Plan)11 LinkedList (java.util.LinkedList)10 SubscriptionCatalog (org.killbill.billing.subscription.catalog.SubscriptionCatalog)10 AccountApiException (org.killbill.billing.account.api.AccountApiException)8 PlanPhasePriceOverridesWithCallContext (org.killbill.billing.catalog.api.PlanPhasePriceOverridesWithCallContext)8 EntitlementApiException (org.killbill.billing.entitlement.api.EntitlementApiException)8