Search in sources :

Example 16 with Catalog

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

the class DefaultSubscriptionBaseTransferApi method createEvent.

private SubscriptionBaseEvent createEvent(final boolean firstEvent, final ExistingEvent existingEvent, final DefaultSubscriptionBase subscription, final DateTime transferDate, final InternalTenantContext context) throws CatalogApiException {
    SubscriptionBaseEvent newEvent = null;
    final Catalog catalog = catalogService.getFullCatalog(true, true, context);
    final DateTime effectiveDate = existingEvent.getEffectiveDate().isBefore(transferDate) ? transferDate : existingEvent.getEffectiveDate();
    final PlanPhaseSpecifier spec = existingEvent.getPlanPhaseSpecifier();
    final PlanPhase currentPhase = existingEvent.getPlanPhaseName() != null ? catalog.findPhase(existingEvent.getPlanPhaseName(), effectiveDate, subscription.getAlignStartDate()) : null;
    if (spec == null || currentPhase == null) {
        // Ignore cancellations - we assume that transferred subscriptions should always be active
        return null;
    }
    final ApiEventBuilder apiBuilder = new ApiEventBuilder().setSubscriptionId(subscription.getId()).setEventPlan(existingEvent.getPlanName()).setEventPlanPhase(currentPhase.getName()).setEventPriceList(spec.getPriceListName()).setEffectiveDate(effectiveDate).setFromDisk(true);
    switch(existingEvent.getSubscriptionTransitionType()) {
        case TRANSFER:
        case CREATE:
            newEvent = new ApiEventTransfer(apiBuilder);
            break;
        // Should we even keep future change events; product question really
        case CHANGE:
            newEvent = firstEvent ? new ApiEventTransfer(apiBuilder) : new ApiEventChange(apiBuilder);
            break;
        case PHASE:
            newEvent = firstEvent ? new ApiEventTransfer(apiBuilder) : PhaseEventData.createNextPhaseEvent(subscription.getId(), currentPhase.getName(), effectiveDate);
            break;
        case CANCEL:
            break;
        default:
            throw new SubscriptionBaseError(String.format("Unexpected transitionType %s", existingEvent.getSubscriptionTransitionType()));
    }
    return newEvent;
}
Also used : PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) ApiEventBuilder(org.killbill.billing.subscription.events.user.ApiEventBuilder) SubscriptionBaseError(org.killbill.billing.subscription.exceptions.SubscriptionBaseError) PlanPhase(org.killbill.billing.catalog.api.PlanPhase) ApiEventTransfer(org.killbill.billing.subscription.events.user.ApiEventTransfer) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent) Catalog(org.killbill.billing.catalog.api.Catalog) DateTime(org.joda.time.DateTime) ApiEventChange(org.killbill.billing.subscription.events.user.ApiEventChange)

Example 17 with Catalog

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

the class DefaultSubscriptionBaseApiService method doCancelPlan.

private boolean doCancelPlan(final Map<DefaultSubscriptionBase, DateTime> subscriptions, final DateTime now, final InternalCallContext internalCallContext) throws SubscriptionBaseApiException {
    final List<DefaultSubscriptionBase> subscriptionsToBeCancelled = new LinkedList<DefaultSubscriptionBase>();
    final List<SubscriptionBaseEvent> cancelEvents = new LinkedList<SubscriptionBaseEvent>();
    try {
        for (final DefaultSubscriptionBase subscription : subscriptions.keySet()) {
            final DateTime effectiveDate = subscriptions.get(subscription);
            validateEffectiveDate(subscription, effectiveDate);
            subscriptionsToBeCancelled.add(subscription);
            cancelEvents.addAll(getEventsOnCancelPlan(subscription, effectiveDate, now, false, internalCallContext));
            if (subscription.getCategory() == ProductCategory.BASE) {
                subscriptionsToBeCancelled.addAll(computeAddOnsToCancel(cancelEvents, null, subscription.getBundleId(), effectiveDate, internalCallContext));
            }
        }
        dao.cancelSubscriptions(subscriptionsToBeCancelled, cancelEvents, internalCallContext);
        boolean allSubscriptionsCancelled = true;
        for (final DefaultSubscriptionBase subscription : subscriptions.keySet()) {
            final Catalog fullCatalog = catalogService.getFullCatalog(true, true, internalCallContext);
            subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId(), internalCallContext), fullCatalog);
            allSubscriptionsCancelled = allSubscriptionsCancelled && (subscription.getState() == EntitlementState.CANCELLED);
        }
        return allSubscriptionsCancelled;
    } catch (final CatalogApiException e) {
        throw new SubscriptionBaseApiException(e);
    }
}
Also used : CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent) LinkedList(java.util.LinkedList) DateTime(org.joda.time.DateTime) Catalog(org.killbill.billing.catalog.api.Catalog)

Example 18 with Catalog

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

the class DefaultSubscriptionBaseApiService method uncancel.

@Override
public boolean uncancel(final DefaultSubscriptionBase subscription, final CallContext context) throws SubscriptionBaseApiException {
    if (!subscription.isSubscriptionFutureCancelled()) {
        throw new SubscriptionBaseApiException(ErrorCode.SUB_UNCANCEL_BAD_STATE, subscription.getId().toString());
    }
    final DateTime now = clock.getUTCNow();
    final SubscriptionBaseEvent uncancelEvent = new ApiEventUncancel(new ApiEventBuilder().setSubscriptionId(subscription.getId()).setEffectiveDate(now).setFromDisk(true));
    final List<SubscriptionBaseEvent> uncancelEvents = new ArrayList<SubscriptionBaseEvent>();
    uncancelEvents.add(uncancelEvent);
    final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
    //
    // Used to compute effective for next phase (which was set unactive during cancellation).
    // In case of a pending subscription we don't want to pass an effective date prior the CREATE event as we would end up with the wrong
    // transition in PlanAligner (next transition would be CREATE instead of potential next PHASE)
    //
    final DateTime planAlignerEffectiveDate = subscription.getState() == EntitlementState.PENDING ? subscription.getStartDate() : now;
    final TimedPhase nextTimedPhase = planAligner.getNextTimedPhase(subscription, planAlignerEffectiveDate, internalCallContext);
    final PhaseEvent nextPhaseEvent = (nextTimedPhase != null) ? PhaseEventData.createNextPhaseEvent(subscription.getId(), nextTimedPhase.getPhase().getName(), nextTimedPhase.getStartPhase()) : null;
    if (nextPhaseEvent != null) {
        uncancelEvents.add(nextPhaseEvent);
    }
    dao.uncancelSubscription(subscription, uncancelEvents, internalCallContext);
    try {
        final Catalog fullCatalog = catalogService.getFullCatalog(true, true, internalCallContext);
        subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId(), internalCallContext), fullCatalog);
        return true;
    } catch (final CatalogApiException e) {
        throw new SubscriptionBaseApiException(e);
    }
}
Also used : PhaseEvent(org.killbill.billing.subscription.events.phase.PhaseEvent) ApiEventBuilder(org.killbill.billing.subscription.events.user.ApiEventBuilder) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) ArrayList(java.util.ArrayList) TimedPhase(org.killbill.billing.subscription.alignment.TimedPhase) ApiEventUncancel(org.killbill.billing.subscription.events.user.ApiEventUncancel) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent) DateTime(org.joda.time.DateTime) Catalog(org.killbill.billing.catalog.api.Catalog) PlanPhasePriceOverride(org.killbill.billing.catalog.api.PlanPhasePriceOverride)

Example 19 with Catalog

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

the class DefaultSubscriptionBaseApiService method doChangePlan.

private void doChangePlan(final DefaultSubscriptionBase subscription, final PlanSpecifier spec, final List<PlanPhasePriceOverride> overrides, final DateTime effectiveDate, final CallContext context) throws SubscriptionBaseApiException, CatalogApiException {
    final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
    final PlanPhasePriceOverridesWithCallContext overridesWithContext = new DefaultPlanPhasePriceOverridesWithCallContext(overrides, context);
    final Plan newPlan = catalogService.getFullCatalog(true, true, internalCallContext).createOrFindPlan(spec, overridesWithContext, effectiveDate, subscription.getStartDate());
    final PhaseType initialPhaseType;
    if (overrides != null && overrides.size() == 1 && overrides.get(0).getPlanPhaseSpecifier() != null && overrides.get(0).getCurrency() == null) {
        initialPhaseType = overrides.get(0).getPlanPhaseSpecifier().getPhaseType();
    } else {
        initialPhaseType = null;
    }
    if (ProductCategory.ADD_ON.toString().equalsIgnoreCase(newPlan.getProduct().getCategory().toString())) {
        if (newPlan.getPlansAllowedInBundle() != -1 && newPlan.getPlansAllowedInBundle() > 0 && addonUtils.countExistingAddOnsWithSamePlanName(dao.getSubscriptions(subscription.getBundleId(), null, internalCallContext), newPlan.getName()) >= newPlan.getPlansAllowedInBundle()) {
            // the plan can be changed to the new value, because it has reached its limit by bundle
            throw new SubscriptionBaseApiException(ErrorCode.SUB_CHANGE_AO_MAX_PLAN_ALLOWED_BY_BUNDLE, newPlan.getName());
        }
    }
    if (newPlan.getProduct().getCategory() != subscription.getCategory()) {
        throw new SubscriptionBaseApiException(ErrorCode.SUB_CHANGE_INVALID, subscription.getId());
    }
    final List<DefaultSubscriptionBase> addOnSubscriptionsToBeCancelled = new ArrayList<DefaultSubscriptionBase>();
    final List<SubscriptionBaseEvent> addOnCancelEvents = new ArrayList<SubscriptionBaseEvent>();
    final List<SubscriptionBaseEvent> changeEvents = getEventsOnChangePlan(subscription, newPlan, newPlan.getPriceListName(), effectiveDate, true, addOnSubscriptionsToBeCancelled, addOnCancelEvents, initialPhaseType, internalCallContext);
    dao.changePlan(subscription, changeEvents, addOnSubscriptionsToBeCancelled, addOnCancelEvents, internalCallContext);
    final Catalog fullCatalog = catalogService.getFullCatalog(true, true, internalCallContext);
    subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId(), internalCallContext), fullCatalog);
}
Also used : PlanPhasePriceOverridesWithCallContext(org.killbill.billing.catalog.api.PlanPhasePriceOverridesWithCallContext) DefaultPlanPhasePriceOverridesWithCallContext(org.killbill.billing.subscription.api.svcs.DefaultPlanPhasePriceOverridesWithCallContext) PhaseType(org.killbill.billing.catalog.api.PhaseType) ArrayList(java.util.ArrayList) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) Plan(org.killbill.billing.catalog.api.Plan) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent) DefaultPlanPhasePriceOverridesWithCallContext(org.killbill.billing.subscription.api.svcs.DefaultPlanPhasePriceOverridesWithCallContext) Catalog(org.killbill.billing.catalog.api.Catalog)

Aggregations

Catalog (org.killbill.billing.catalog.api.Catalog)19 DateTime (org.joda.time.DateTime)10 CatalogApiException (org.killbill.billing.catalog.api.CatalogApiException)7 InternalCallContext (org.killbill.billing.callcontext.InternalCallContext)6 Plan (org.killbill.billing.catalog.api.Plan)5 PlanPhasePriceOverride (org.killbill.billing.catalog.api.PlanPhasePriceOverride)5 PlanPhasePriceOverridesWithCallContext (org.killbill.billing.catalog.api.PlanPhasePriceOverridesWithCallContext)5 SubscriptionBaseApiException (org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)5 SubscriptionBaseEvent (org.killbill.billing.subscription.events.SubscriptionBaseEvent)5 SubscriptionBaseError (org.killbill.billing.subscription.exceptions.SubscriptionBaseError)4 ArrayList (java.util.ArrayList)3 UUID (java.util.UUID)3 DefaultCatalogService (org.killbill.billing.catalog.DefaultCatalogService)3 PlanPhaseSpecifier (org.killbill.billing.catalog.api.PlanPhaseSpecifier)3 DefaultSubscriptionBase (org.killbill.billing.subscription.api.user.DefaultSubscriptionBase)3 SubscriptionBaseBundle (org.killbill.billing.subscription.api.user.SubscriptionBaseBundle)3 SubscriptionBuilder (org.killbill.billing.subscription.api.user.SubscriptionBuilder)3 CallContext (org.killbill.billing.util.callcontext.CallContext)3 InternalTenantContext (org.killbill.billing.callcontext.InternalTenantContext)2 PhaseType (org.killbill.billing.catalog.api.PhaseType)2