Search in sources :

Example 21 with CatalogApiException

use of org.killbill.billing.catalog.api.CatalogApiException in project killbill by killbill.

the class AccountResource method getAccountBundles.

@TimedResource
@GET
@Path("/{accountId:" + UUID_PATTERN + "}/" + BUNDLES)
@Produces(APPLICATION_JSON)
@ApiOperation(value = "Retrieve bundles for account", response = BundleJson.class, responseContainer = "List")
@ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid account id supplied"), @ApiResponse(code = 404, message = "Account not found") })
public Response getAccountBundles(@PathParam("accountId") final String accountId, @QueryParam(QUERY_EXTERNAL_KEY) final String externalKey, @QueryParam(QUERY_BUNDLES_FILTER) final String bundlesFilter, @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode, @javax.ws.rs.core.Context final HttpServletRequest request) throws AccountApiException, SubscriptionApiException {
    final TenantContext tenantContext = context.createContext(request);
    final UUID uuid = UUID.fromString(accountId);
    final Account account = accountUserApi.getAccountById(uuid, tenantContext);
    final List<SubscriptionBundle> bundles = (externalKey != null) ? subscriptionApi.getSubscriptionBundlesForAccountIdAndExternalKey(uuid, externalKey, tenantContext) : subscriptionApi.getSubscriptionBundlesForAccountId(uuid, tenantContext);
    final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(account.getId(), auditMode.getLevel(), tenantContext);
    boolean filter = (null != bundlesFilter && !bundlesFilter.isEmpty());
    final Collection<BundleJson> result = Collections2.transform((filter) ? filterBundles(bundles, Arrays.asList(bundlesFilter.split(","))) : bundles, new Function<SubscriptionBundle, BundleJson>() {

        @Override
        public BundleJson apply(final SubscriptionBundle input) {
            try {
                return new BundleJson(input, account.getCurrency(), accountAuditLogs);
            } catch (final CatalogApiException e) {
                // Not the cleanest thing, but guava Api don't allow throw..
                throw new RuntimeException(e);
            }
        }
    });
    return Response.status(Status.OK).entity(result).build();
}
Also used : Account(org.killbill.billing.account.api.Account) TenantContext(org.killbill.billing.util.callcontext.TenantContext) BundleJson(org.killbill.billing.jaxrs.json.BundleJson) SubscriptionBundle(org.killbill.billing.entitlement.api.SubscriptionBundle) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) UUID(java.util.UUID) AccountAuditLogs(org.killbill.billing.util.audit.AccountAuditLogs) Path(javax.ws.rs.Path) TimedResource(org.killbill.commons.metrics.TimedResource) Produces(javax.ws.rs.Produces) GET(javax.ws.rs.GET) ApiOperation(io.swagger.annotations.ApiOperation) ApiResponses(io.swagger.annotations.ApiResponses)

Example 22 with CatalogApiException

use of org.killbill.billing.catalog.api.CatalogApiException in project killbill by killbill.

the class DefaultSubscriptionBaseTransferApi method transferBundle.

@Override
public SubscriptionBaseBundle transferBundle(final UUID sourceAccountId, final UUID destAccountId, final String bundleKey, final DateTime transferDate, final boolean transferAddOn, final boolean cancelImmediately, final CallContext context) throws SubscriptionBaseTransferApiException {
    final InternalCallContext fromInternalCallContext = internalCallContextFactory.createInternalCallContext(sourceAccountId, context);
    final InternalCallContext toInternalCallContext = internalCallContextFactory.createInternalCallContext(destAccountId, context);
    try {
        final DateTime effectiveTransferDate = transferDate == null ? clock.getUTCNow() : transferDate;
        if (effectiveTransferDate.isAfter(clock.getUTCNow())) {
            // (subscription always expects the first event to be in the past)
            throw new SubscriptionBaseTransferApiException(ErrorCode.SUB_TRANSFER_INVALID_EFF_DATE, effectiveTransferDate);
        }
        final List<SubscriptionBaseBundle> bundlesForAccountAndKey = dao.getSubscriptionBundlesForAccountAndKey(sourceAccountId, bundleKey, fromInternalCallContext);
        final SubscriptionBaseBundle bundle = DefaultSubscriptionInternalApi.getActiveBundleForKeyNotException(bundlesForAccountAndKey, dao, clock, fromInternalCallContext);
        if (bundle == null) {
            throw new SubscriptionBaseTransferApiException(ErrorCode.SUB_CREATE_NO_BUNDLE, bundleKey);
        }
        // Get the bundle timeline for the old account
        final BundleBaseTimeline bundleBaseTimeline = timelineApi.getBundleTimeline(bundle, context);
        final DefaultSubscriptionBaseBundle subscriptionBundleData = new DefaultSubscriptionBaseBundle(bundleKey, destAccountId, effectiveTransferDate, bundle.getOriginalCreatedDate(), clock.getUTCNow(), clock.getUTCNow());
        final List<SubscriptionTransferData> subscriptionTransferDataList = new LinkedList<SubscriptionTransferData>();
        final List<TransferCancelData> transferCancelDataList = new LinkedList<TransferCancelData>();
        DateTime bundleStartdate = null;
        for (final SubscriptionBaseTimeline cur : bundleBaseTimeline.getSubscriptions()) {
            final DefaultSubscriptionBase oldSubscription = (DefaultSubscriptionBase) dao.getSubscriptionFromId(cur.getId(), fromInternalCallContext);
            // Skip already cancelled subscriptions
            if (oldSubscription.getState() == EntitlementState.CANCELLED) {
                continue;
            }
            final List<ExistingEvent> existingEvents = cur.getExistingEvents();
            final ProductCategory productCategory = existingEvents.get(0).getProductCategory();
            // on base plan cancellations, even though we don't support un-transfer today)
            if (productCategory != ProductCategory.ADD_ON || cancelImmediately) {
                // Create the cancelWithRequestedDate event on effectiveCancelDate
                final DateTime effectiveCancelDate = !cancelImmediately && oldSubscription.getChargedThroughDate() != null && effectiveTransferDate.isBefore(oldSubscription.getChargedThroughDate()) ? oldSubscription.getChargedThroughDate() : effectiveTransferDate;
                final SubscriptionBaseEvent cancelEvent = new ApiEventCancel(new ApiEventBuilder().setSubscriptionId(cur.getId()).setEffectiveDate(effectiveCancelDate).setFromDisk(true));
                final TransferCancelData cancelData = new TransferCancelData(oldSubscription, cancelEvent);
                transferCancelDataList.add(cancelData);
            }
            if (productCategory == ProductCategory.ADD_ON && !transferAddOn) {
                continue;
            }
            // We Align with the original subscription
            final DateTime subscriptionAlignStartDate = oldSubscription.getAlignStartDate();
            if (bundleStartdate == null) {
                bundleStartdate = oldSubscription.getStartDate();
            }
            // Create the new subscription for the new bundle on the new account
            final DefaultSubscriptionBase defaultSubscriptionBase = createSubscriptionForApiUse(new SubscriptionBuilder().setId(UUIDs.randomUUID()).setBundleId(subscriptionBundleData.getId()).setBundleExternalKey(subscriptionBundleData.getExternalKey()).setCategory(productCategory).setBundleStartDate(effectiveTransferDate).setAlignStartDate(subscriptionAlignStartDate), ImmutableList.<SubscriptionBaseEvent>of(), fromInternalCallContext);
            final List<SubscriptionBaseEvent> events = toEvents(existingEvents, defaultSubscriptionBase, effectiveTransferDate, fromInternalCallContext);
            final SubscriptionTransferData curData = new SubscriptionTransferData(defaultSubscriptionBase, events, null);
            subscriptionTransferDataList.add(curData);
        }
        BundleTransferData bundleTransferData = new BundleTransferData(subscriptionBundleData, subscriptionTransferDataList);
        // Atomically cancelWithRequestedDate all subscription on old account and create new bundle, subscriptions, events for new account
        dao.transfer(sourceAccountId, destAccountId, bundleTransferData, transferCancelDataList, fromInternalCallContext, toInternalCallContext);
        return bundleTransferData.getData();
    } catch (SubscriptionBaseRepairException e) {
        throw new SubscriptionBaseTransferApiException(e);
    } catch (CatalogApiException e) {
        throw new SubscriptionBaseTransferApiException(e);
    }
}
Also used : InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) SubscriptionBaseTimeline(org.killbill.billing.subscription.api.timeline.SubscriptionBaseTimeline) DateTime(org.joda.time.DateTime) ApiEventBuilder(org.killbill.billing.subscription.events.user.ApiEventBuilder) SubscriptionBaseBundle(org.killbill.billing.subscription.api.user.SubscriptionBaseBundle) DefaultSubscriptionBaseBundle(org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseBundle) DefaultSubscriptionBase(org.killbill.billing.subscription.api.user.DefaultSubscriptionBase) ExistingEvent(org.killbill.billing.subscription.api.timeline.SubscriptionBaseTimeline.ExistingEvent) BundleBaseTimeline(org.killbill.billing.subscription.api.timeline.BundleBaseTimeline) SubscriptionBaseRepairException(org.killbill.billing.subscription.api.timeline.SubscriptionBaseRepairException) DefaultSubscriptionBaseBundle(org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseBundle) ApiEventCancel(org.killbill.billing.subscription.events.user.ApiEventCancel) SubscriptionBuilder(org.killbill.billing.subscription.api.user.SubscriptionBuilder) LinkedList(java.util.LinkedList) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) ProductCategory(org.killbill.billing.catalog.api.ProductCategory) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent)

Example 23 with CatalogApiException

use of org.killbill.billing.catalog.api.CatalogApiException in project killbill by killbill.

the class DefaultSubscriptionBaseApiService method getPlanChangeResult.

@Override
public PlanChangeResult getPlanChangeResult(final DefaultSubscriptionBase subscription, final PlanSpecifier toPlanPhase, final DateTime effectiveDate, final TenantContext context) throws SubscriptionBaseApiException {
    final PlanChangeResult planChangeResult;
    try {
        final InternalTenantContext internalCallContext = createTenantContextFromBundleId(subscription.getBundleId(), context);
        final Plan currentPlan = subscription.getCurrentPlan();
        final PlanPhaseSpecifier fromPlanPhase = new PlanPhaseSpecifier(currentPlan.getName(), subscription.getCurrentPhase().getPhaseType());
        planChangeResult = catalogService.getFullCatalog(true, true, internalCallContext).planChange(fromPlanPhase, toPlanPhase, effectiveDate);
    } catch (final CatalogApiException e) {
        throw new SubscriptionBaseApiException(e);
    }
    return planChangeResult;
}
Also used : PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) InternalTenantContext(org.killbill.billing.callcontext.InternalTenantContext) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) PlanChangeResult(org.killbill.billing.catalog.api.PlanChangeResult) Plan(org.killbill.billing.catalog.api.Plan) PlanPhasePriceOverride(org.killbill.billing.catalog.api.PlanPhasePriceOverride)

Example 24 with CatalogApiException

use of org.killbill.billing.catalog.api.CatalogApiException in project killbill by killbill.

the class DefaultSubscriptionBaseApiService method cancel.

@Override
public boolean cancel(final DefaultSubscriptionBase subscription, final CallContext context) throws SubscriptionBaseApiException {
    final EntitlementState currentState = subscription.getState();
    if (currentState == EntitlementState.CANCELLED) {
        throw new SubscriptionBaseApiException(ErrorCode.SUB_CANCEL_BAD_STATE, subscription.getId(), currentState);
    }
    final DateTime now = clock.getUTCNow();
    final Plan currentPlan = subscription.getCurrentPlan();
    final PlanPhaseSpecifier planPhase = new PlanPhaseSpecifier(currentPlan.getName(), null);
    try {
        final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
        final BillingActionPolicy policy = catalogService.getFullCatalog(true, true, internalCallContext).planCancelPolicy(planPhase, now);
        Preconditions.checkState(policy != BillingActionPolicy.START_OF_TERM, "A default START_OF_TERM policy is not availaible");
        final DateTime effectiveDate = subscription.getPlanChangeEffectiveDate(policy, null, null, -1, null);
        return doCancelPlan(ImmutableMap.<DefaultSubscriptionBase, DateTime>of(subscription, effectiveDate), now, internalCallContext);
    } catch (final CatalogApiException e) {
        throw new SubscriptionBaseApiException(e);
    }
}
Also used : PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) BillingActionPolicy(org.killbill.billing.catalog.api.BillingActionPolicy) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) Plan(org.killbill.billing.catalog.api.Plan) EntitlementState(org.killbill.billing.entitlement.api.Entitlement.EntitlementState) DateTime(org.joda.time.DateTime) PlanPhasePriceOverride(org.killbill.billing.catalog.api.PlanPhasePriceOverride)

Example 25 with CatalogApiException

use of org.killbill.billing.catalog.api.CatalogApiException in project killbill by killbill.

the class TenantCatalogCacheLoader method load.

@Override
public Object load(final Object key, final Object argument) {
    checkCacheLoaderStatus();
    if (!(key instanceof Long)) {
        throw new IllegalArgumentException("Unexpected key type of " + key.getClass().getName());
    }
    if (!(argument instanceof CacheLoaderArgument)) {
        throw new IllegalArgumentException("Unexpected argument type of " + argument.getClass().getName());
    }
    final Long tenantRecordId = (Long) key;
    final InternalTenantContext internalTenantContext = new InternalTenantContext(tenantRecordId);
    final CacheLoaderArgument cacheLoaderArgument = (CacheLoaderArgument) argument;
    if (cacheLoaderArgument.getArgs() == null || !(cacheLoaderArgument.getArgs()[0] instanceof LoaderCallback)) {
        throw new IllegalArgumentException("Missing LoaderCallback from the arguments ");
    }
    final LoaderCallback callback = (LoaderCallback) cacheLoaderArgument.getArgs()[0];
    final List<String> catalogXMLs = tenantApi.getTenantCatalogs(internalTenantContext);
    if (catalogXMLs.isEmpty()) {
        return null;
    }
    try {
        log.info("Loading catalog cache for tenantRecordId='{}'", internalTenantContext.getTenantRecordId());
        return callback.loadCatalog(catalogXMLs, tenantRecordId);
    } catch (final CatalogApiException e) {
        throw new IllegalStateException(String.format("Failed to de-serialize catalog for tenantRecordId='%s'", internalTenantContext.getTenantRecordId()), e);
    }
}
Also used : InternalTenantContext(org.killbill.billing.callcontext.InternalTenantContext) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException)

Aggregations

CatalogApiException (org.killbill.billing.catalog.api.CatalogApiException)61 PlanPhasePriceOverride (org.killbill.billing.catalog.api.PlanPhasePriceOverride)22 DateTime (org.joda.time.DateTime)20 SubscriptionBaseApiException (org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)14 InternalCallContext (org.killbill.billing.callcontext.InternalCallContext)12 Plan (org.killbill.billing.catalog.api.Plan)12 DefaultSubscriptionBase (org.killbill.billing.subscription.api.user.DefaultSubscriptionBase)11 ArrayList (java.util.ArrayList)9 UUID (java.util.UUID)9 InternalTenantContext (org.killbill.billing.callcontext.InternalTenantContext)8 PlanPhaseSpecifier (org.killbill.billing.catalog.api.PlanPhaseSpecifier)8 SubscriptionBaseEvent (org.killbill.billing.subscription.events.SubscriptionBaseEvent)8 LinkedList (java.util.LinkedList)7 Catalog (org.killbill.billing.catalog.api.Catalog)7 Test (org.testng.annotations.Test)7 StandaloneCatalog (org.killbill.billing.catalog.StandaloneCatalog)6 PlanSpecifier (org.killbill.billing.catalog.api.PlanSpecifier)6 URI (java.net.URI)5 PlanPhase (org.killbill.billing.catalog.api.PlanPhase)5 SubscriptionBase (org.killbill.billing.subscription.api.SubscriptionBase)5