Search in sources :

Example 6 with BillingActionPolicy

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

the class DefaultSubscriptionBaseApiService method cancel.

@Override
public boolean cancel(final DefaultSubscriptionBase subscription, final CallContext context) throws SubscriptionBaseApiException {
    final Plan currentPlan = subscription.getCurrentOrPendingPlan();
    final PlanPhaseSpecifier planPhase = new PlanPhaseSpecifier(currentPlan.getName(), null);
    try {
        final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
        final SubscriptionCatalog catalog = subscriptionCatalogApi.getFullCatalog(internalCallContext);
        final BillingActionPolicy policy = catalog.planCancelPolicy(planPhase, clock.getUTCNow(), subscription.getStartDate());
        Preconditions.checkState(policy != BillingActionPolicy.START_OF_TERM, "A default START_OF_TERM policy is not availaible");
        final DateTime effectiveDate = subscription.getEffectiveDateForPolicy(policy, null, -1, null);
        return doCancelPlan(ImmutableMap.<DefaultSubscriptionBase, DateTime>of(subscription, effectiveDate), catalog, 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) SubscriptionCatalog(org.killbill.billing.subscription.catalog.SubscriptionCatalog) DateTime(org.joda.time.DateTime)

Example 7 with BillingActionPolicy

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

the class DefaultSubscriptionBaseApiService method dryRunChangePlan.

@Override
public DateTime dryRunChangePlan(final DefaultSubscriptionBase subscription, final EntitlementSpecifier spec, @Nullable final DateTime requestedDateWithMs, @Nullable final BillingActionPolicy requestedPolicy, final TenantContext context) throws SubscriptionBaseApiException {
    final DateTime now = clock.getUTCNow();
    BillingActionPolicy policyMaybeNull = requestedPolicy;
    if (requestedDateWithMs == null && requestedPolicy == null) {
        final PlanChangeResult planChangeResult = getPlanChangeResult(subscription, spec.getPlanPhaseSpecifier(), now, context);
        policyMaybeNull = planChangeResult.getPolicy();
    }
    logger.debug("dryRunChangePlan: requestedPolicy='{}', actualPolicy='{}', requestedDateWithMs='{}'", requestedPolicy, policyMaybeNull, requestedDateWithMs);
    if (policyMaybeNull != null) {
        return subscription.getEffectiveDateForPolicy(policyMaybeNull, null, -1, null);
    } else if (requestedDateWithMs != null) {
        return DefaultClock.truncateMs(requestedDateWithMs);
    } else {
        return now;
    }
}
Also used : BillingActionPolicy(org.killbill.billing.catalog.api.BillingActionPolicy) PlanChangeResult(org.killbill.billing.catalog.api.PlanChangeResult) DateTime(org.joda.time.DateTime)

Example 8 with BillingActionPolicy

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

the class DefaultPlanRules method getPlanChangeResult.

@Override
public PlanChangeResult getPlanChangeResult(final PlanPhaseSpecifier from, final PlanSpecifier to) throws CatalogApiException {
    final DefaultPriceList toPriceList = to.getPriceListName() != null ? (DefaultPriceList) root.findPriceList(to.getPriceListName()) : findPriceList(from);
    // If we use old scheme {product, billingPeriod, pricelist}, ensure pricelist is correct
    // (Pricelist may be null because if it is unspecified this is the principal use-case)
    final PlanSpecifier toWithPriceList = to.getPlanName() == null ? new PlanSpecifier(to.getProductName(), to.getBillingPeriod(), toPriceList.getName()) : to;
    final BillingActionPolicy policy = getPlanChangePolicy(from, toWithPriceList);
    if (policy == BillingActionPolicy.ILLEGAL) {
        throw new IllegalPlanChange(from, toWithPriceList);
    }
    final PlanAlignmentChange alignment = getPlanChangeAlignment(from, toWithPriceList);
    return new PlanChangeResult(toPriceList, policy, alignment);
}
Also used : BillingActionPolicy(org.killbill.billing.catalog.api.BillingActionPolicy) IllegalPlanChange(org.killbill.billing.catalog.api.IllegalPlanChange) PlanAlignmentChange(org.killbill.billing.catalog.api.PlanAlignmentChange) DefaultPriceList(org.killbill.billing.catalog.DefaultPriceList) PlanChangeResult(org.killbill.billing.catalog.api.PlanChangeResult) PlanSpecifier(org.killbill.billing.catalog.api.PlanSpecifier)

Example 9 with BillingActionPolicy

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

the class DefaultSubscriptionInternalApi method populateDryRunEvents.

private void populateDryRunEvents(@Nullable final UUID bundleId, @Nullable final DryRunArguments dryRunArguments, final Collection<SubscriptionBaseEvent> outputDryRunEvents, final Collection<SubscriptionBase> outputSubscriptions, final InternalTenantContext context) throws SubscriptionBaseApiException {
    if (dryRunArguments == null || dryRunArguments.getAction() == null) {
        return;
    }
    final DateTime utcNow = clock.getUTCNow();
    List<SubscriptionBaseEvent> dryRunEvents = null;
    try {
        final PlanPhaseSpecifier inputSpec = dryRunArguments.getPlanPhaseSpecifier();
        final boolean isInputSpecNullOrEmpty = inputSpec == null || (inputSpec.getPlanName() == null && inputSpec.getProductName() == null && inputSpec.getBillingPeriod() == null);
        final Catalog catalog = catalogService.getFullCatalog(true, true, context);
        // Create an overridesWithContext with a null context to indicate this is dryRun and no price overriden plan should be created.
        final PlanPhasePriceOverridesWithCallContext overridesWithContext = new DefaultPlanPhasePriceOverridesWithCallContext(dryRunArguments.getPlanPhasePriceOverrides(), null);
        final Plan plan = isInputSpecNullOrEmpty ? null : catalog.createOrFindPlan(inputSpec, overridesWithContext, utcNow);
        final TenantContext tenantContext = internalCallContextFactory.createTenantContext(context);
        switch(dryRunArguments.getAction()) {
            case START_BILLING:
                final DefaultSubscriptionBase baseSubscription = (DefaultSubscriptionBase) dao.getBaseSubscription(bundleId, context);
                final DateTime startEffectiveDate = dryRunArguments.getEffectiveDate() != null ? context.toUTCDateTime(dryRunArguments.getEffectiveDate()) : utcNow;
                final DateTime bundleStartDate = getBundleStartDateWithSanity(bundleId, baseSubscription, plan, startEffectiveDate, context);
                final UUID subscriptionId = UUIDs.randomUUID();
                dryRunEvents = apiService.getEventsOnCreation(bundleId, subscriptionId, startEffectiveDate, bundleStartDate, plan, inputSpec.getPhaseType(), plan.getPriceListName(), startEffectiveDate, utcNow, context);
                final SubscriptionBuilder builder = new SubscriptionBuilder().setId(subscriptionId).setBundleId(bundleId).setBundleExternalKey(null).setCategory(plan.getProduct().getCategory()).setBundleStartDate(bundleStartDate).setAlignStartDate(startEffectiveDate);
                final DefaultSubscriptionBase newSubscription = new DefaultSubscriptionBase(builder, apiService, clock);
                newSubscription.rebuildTransitions(dryRunEvents, catalog);
                outputSubscriptions.add(newSubscription);
                break;
            case CHANGE:
                final DefaultSubscriptionBase subscriptionForChange = (DefaultSubscriptionBase) dao.getSubscriptionFromId(dryRunArguments.getSubscriptionId(), context);
                DateTime changeEffectiveDate = dryRunArguments.getEffectiveDate() != null ? context.toUTCDateTime(dryRunArguments.getEffectiveDate()) : null;
                if (changeEffectiveDate == null) {
                    BillingActionPolicy policy = dryRunArguments.getBillingActionPolicy();
                    if (policy == null) {
                        final PlanChangeResult planChangeResult = apiService.getPlanChangeResult(subscriptionForChange, inputSpec, utcNow, tenantContext);
                        policy = planChangeResult.getPolicy();
                    }
                    // We pass null for billingAlignment, accountTimezone, account BCD because this is not available which means that dryRun with START_OF_TERM BillingPolicy will fail
                    changeEffectiveDate = subscriptionForChange.getPlanChangeEffectiveDate(policy, null, null, -1, context);
                }
                dryRunEvents = apiService.getEventsOnChangePlan(subscriptionForChange, plan, plan.getPriceListName(), changeEffectiveDate, utcNow, true, context);
                break;
            case STOP_BILLING:
                final DefaultSubscriptionBase subscriptionForCancellation = (DefaultSubscriptionBase) dao.getSubscriptionFromId(dryRunArguments.getSubscriptionId(), context);
                DateTime cancelEffectiveDate = dryRunArguments.getEffectiveDate() != null ? context.toUTCDateTime(dryRunArguments.getEffectiveDate()) : null;
                if (dryRunArguments.getEffectiveDate() == null) {
                    BillingActionPolicy policy = dryRunArguments.getBillingActionPolicy();
                    if (policy == null) {
                        final Plan currentPlan = subscriptionForCancellation.getCurrentPlan();
                        final PlanPhaseSpecifier spec = new PlanPhaseSpecifier(currentPlan.getName(), subscriptionForCancellation.getCurrentPhase().getPhaseType());
                        policy = catalogService.getFullCatalog(true, true, context).planCancelPolicy(spec, utcNow);
                    }
                    // We pass null for billingAlignment, accountTimezone, account BCD because this is not available which means that dryRun with START_OF_TERM BillingPolicy will fail
                    cancelEffectiveDate = subscriptionForCancellation.getPlanChangeEffectiveDate(policy, null, null, -1, context);
                }
                dryRunEvents = apiService.getEventsOnCancelPlan(subscriptionForCancellation, cancelEffectiveDate, utcNow, true, context);
                break;
            default:
                throw new IllegalArgumentException("Unexpected dryRunArguments action " + dryRunArguments.getAction());
        }
    } catch (final CatalogApiException e) {
        throw new SubscriptionBaseApiException(e);
    }
    if (dryRunEvents != null && !dryRunEvents.isEmpty()) {
        outputDryRunEvents.addAll(dryRunEvents);
    }
}
Also used : PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) BillingActionPolicy(org.killbill.billing.catalog.api.BillingActionPolicy) InternalTenantContext(org.killbill.billing.callcontext.InternalTenantContext) TenantContext(org.killbill.billing.util.callcontext.TenantContext) PlanChangeResult(org.killbill.billing.catalog.api.PlanChangeResult) SubscriptionBuilder(org.killbill.billing.subscription.api.user.SubscriptionBuilder) Plan(org.killbill.billing.catalog.api.Plan) DateTime(org.joda.time.DateTime) Catalog(org.killbill.billing.catalog.api.Catalog) PlanPhasePriceOverridesWithCallContext(org.killbill.billing.catalog.api.PlanPhasePriceOverridesWithCallContext) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) DefaultSubscriptionBase(org.killbill.billing.subscription.api.user.DefaultSubscriptionBase) UUID(java.util.UUID) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent) SubscriptionBaseApiException(org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)

Example 10 with BillingActionPolicy

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

the class DefaultSubscriptionBaseApiService method dryRunChangePlan.

@Override
public DateTime dryRunChangePlan(final DefaultSubscriptionBase subscription, final PlanSpecifier spec, @Nullable final DateTime requestedDateWithMs, @Nullable final BillingActionPolicy requestedPolicy, final TenantContext context) throws SubscriptionBaseApiException {
    final DateTime now = clock.getUTCNow();
    BillingActionPolicy policyMaybeNull = requestedPolicy;
    if (requestedDateWithMs == null && requestedPolicy == null) {
        final PlanChangeResult planChangeResult = getPlanChangeResult(subscription, spec, now, context);
        policyMaybeNull = planChangeResult.getPolicy();
    }
    if (policyMaybeNull != null) {
        return subscription.getPlanChangeEffectiveDate(policyMaybeNull, null, null, -1, null);
    } else if (requestedDateWithMs != null) {
        return DefaultClock.truncateMs(requestedDateWithMs);
    } else {
        return now;
    }
}
Also used : BillingActionPolicy(org.killbill.billing.catalog.api.BillingActionPolicy) PlanChangeResult(org.killbill.billing.catalog.api.PlanChangeResult) DateTime(org.joda.time.DateTime) PlanPhasePriceOverride(org.killbill.billing.catalog.api.PlanPhasePriceOverride)

Aggregations

BillingActionPolicy (org.killbill.billing.catalog.api.BillingActionPolicy)11 PlanChangeResult (org.killbill.billing.catalog.api.PlanChangeResult)6 UUID (java.util.UUID)5 DateTime (org.joda.time.DateTime)5 LocalDate (org.joda.time.LocalDate)4 CallContext (org.killbill.billing.util.callcontext.CallContext)4 ApiOperation (io.swagger.annotations.ApiOperation)3 ApiResponses (io.swagger.annotations.ApiResponses)3 Path (javax.ws.rs.Path)3 Produces (javax.ws.rs.Produces)3 Plan (org.killbill.billing.catalog.api.Plan)3 PlanPhaseSpecifier (org.killbill.billing.catalog.api.PlanPhaseSpecifier)3 PlanSpecifier (org.killbill.billing.catalog.api.PlanSpecifier)3 Entitlement (org.killbill.billing.entitlement.api.Entitlement)3 PluginProperty (org.killbill.billing.payment.api.PluginProperty)3 TimedResource (org.killbill.commons.metrics.TimedResource)3 ApiResponse (io.swagger.annotations.ApiResponse)2 Consumes (javax.ws.rs.Consumes)2 PUT (javax.ws.rs.PUT)2 Response (javax.ws.rs.core.Response)2