Search in sources :

Example 1 with BillingActionPolicy

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

the class DefaultPlanRules method planChange.

public PlanChangeResult planChange(final PlanPhaseSpecifier from, final PlanSpecifier to, final StaticCatalog catalog) throws CatalogApiException {
    final DefaultPriceList toPriceList = to.getPriceListName() != null ? (DefaultPriceList) catalog.findCurrentPricelist(to.getPriceListName()) : findPriceList(from, catalog);
    // 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, catalog);
    if (policy == BillingActionPolicy.ILLEGAL) {
        throw new IllegalPlanChange(from, toWithPriceList);
    }
    final PlanAlignmentChange alignment = getPlanChangeAlignment(from, toWithPriceList, catalog);
    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 2 with BillingActionPolicy

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

the class BundleResource method transferBundle.

@TimedResource
@PUT
@Path("/{bundleId:" + UUID_PATTERN + "}")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
@ApiOperation(value = "Transfer a bundle to another account")
@ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid bundle id, requested date or policy supplied"), @ApiResponse(code = 404, message = "Bundle not found") })
public Response transferBundle(final BundleJson json, @PathParam(ID_PARAM_NAME) final String id, @QueryParam(QUERY_REQUESTED_DT) final String requestedDate, @QueryParam(QUERY_BILLING_POLICY) @DefaultValue("END_OF_TERM") final String policyString, @QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString, @HeaderParam(HDR_CREATED_BY) final String createdBy, @HeaderParam(HDR_REASON) final String reason, @HeaderParam(HDR_COMMENT) final String comment, @javax.ws.rs.core.Context final UriInfo uriInfo, @javax.ws.rs.core.Context final HttpServletRequest request) throws EntitlementApiException, SubscriptionApiException, AccountApiException {
    verifyNonNullOrEmpty(json, "BundleJson body should be specified");
    verifyNonNullOrEmpty(json.getAccountId(), "BundleJson accountId needs to be set");
    final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
    final BillingActionPolicy policy = BillingActionPolicy.valueOf(policyString.toUpperCase());
    final CallContext callContext = context.createContext(createdBy, reason, comment, request);
    final UUID bundleId = UUID.fromString(id);
    final SubscriptionBundle bundle = subscriptionApi.getSubscriptionBundle(bundleId, callContext);
    final LocalDate inputLocalDate = toLocalDate(requestedDate);
    final UUID newBundleId = entitlementApi.transferEntitlementsOverrideBillingPolicy(bundle.getAccountId(), UUID.fromString(json.getAccountId()), bundle.getExternalKey(), inputLocalDate, policy, pluginProperties, callContext);
    return uriBuilder.buildResponse(uriInfo, BundleResource.class, "getBundle", newBundleId, request);
}
Also used : PluginProperty(org.killbill.billing.payment.api.PluginProperty) BillingActionPolicy(org.killbill.billing.catalog.api.BillingActionPolicy) SubscriptionBundle(org.killbill.billing.entitlement.api.SubscriptionBundle) UUID(java.util.UUID) CallContext(org.killbill.billing.util.callcontext.CallContext) LocalDate(org.joda.time.LocalDate) Path(javax.ws.rs.Path) TimedResource(org.killbill.commons.metrics.TimedResource) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces) ApiOperation(io.swagger.annotations.ApiOperation) PUT(javax.ws.rs.PUT) ApiResponses(io.swagger.annotations.ApiResponses)

Example 3 with BillingActionPolicy

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

the class SubscriptionResource method changeEntitlementPlan.

@TimedResource
@PUT
@Produces(APPLICATION_JSON)
@Consumes(APPLICATION_JSON)
@Path("/{subscriptionId:" + UUID_PATTERN + "}")
@ApiOperation(value = "Change entitlement plan")
@ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid subscription id supplied"), @ApiResponse(code = 404, message = "Entitlement not found") })
public Response changeEntitlementPlan(final SubscriptionJson entitlement, @PathParam("subscriptionId") final String subscriptionId, @QueryParam(QUERY_REQUESTED_DT) final String requestedDate, @QueryParam(QUERY_CALL_COMPLETION) @DefaultValue("false") final Boolean callCompletion, @QueryParam(QUERY_CALL_TIMEOUT) @DefaultValue("3") final long timeoutSec, @QueryParam(QUERY_BILLING_POLICY) final String policyString, @QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString, @HeaderParam(HDR_CREATED_BY) final String createdBy, @HeaderParam(HDR_REASON) final String reason, @HeaderParam(HDR_COMMENT) final String comment, @javax.ws.rs.core.Context final HttpServletRequest request) throws EntitlementApiException, AccountApiException, SubscriptionApiException {
    verifyNonNullOrEmpty(entitlement, "SubscriptionJson body should be specified");
    if (entitlement.getPlanName() == null) {
        verifyNonNullOrEmpty(entitlement.getProductName(), "SubscriptionJson productName needs to be set", entitlement.getBillingPeriod(), "SubscriptionJson billingPeriod needs to be set", entitlement.getPriceList(), "SubscriptionJson priceList needs to be set");
    }
    final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
    final CallContext callContext = context.createContext(createdBy, reason, comment, request);
    final EntitlementCallCompletionCallback<Response> callback = new EntitlementCallCompletionCallback<Response>() {

        private boolean isImmediateOp = true;

        @Override
        public Response doOperation(final CallContext ctx) throws EntitlementApiException, InterruptedException, TimeoutException, AccountApiException {
            final UUID uuid = UUID.fromString(subscriptionId);
            final Entitlement current = entitlementApi.getEntitlementForId(uuid, callContext);
            final LocalDate inputLocalDate = toLocalDate(requestedDate);
            final Entitlement newEntitlement;
            final Account account = accountUserApi.getAccountById(current.getAccountId(), callContext);
            final PlanSpecifier planSpec = entitlement.getPlanName() != null ? new PlanSpecifier(entitlement.getPlanName()) : new PlanSpecifier(entitlement.getProductName(), BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList());
            final List<PlanPhasePriceOverride> overrides = PhasePriceOverrideJson.toPlanPhasePriceOverrides(entitlement.getPriceOverrides(), planSpec, account.getCurrency());
            if (requestedDate == null && policyString == null) {
                newEntitlement = current.changePlan(planSpec, overrides, pluginProperties, ctx);
            } else if (policyString == null) {
                newEntitlement = current.changePlanWithDate(planSpec, overrides, inputLocalDate, pluginProperties, ctx);
            } else {
                final BillingActionPolicy policy = BillingActionPolicy.valueOf(policyString.toUpperCase());
                newEntitlement = current.changePlanOverrideBillingPolicy(planSpec, overrides, inputLocalDate, policy, pluginProperties, ctx);
            }
            isImmediateOp = newEntitlement.getLastActiveProduct().getName().equals(entitlement.getProductName()) && newEntitlement.getLastActivePlan().getRecurringBillingPeriod() == BillingPeriod.valueOf(entitlement.getBillingPeriod()) && newEntitlement.getLastActivePriceList().getName().equals(entitlement.getPriceList());
            return Response.status(Status.OK).build();
        }

        @Override
        public boolean isImmOperation() {
            return isImmediateOp;
        }

        @Override
        public Response doResponseOk(final Response operationResponse) throws SubscriptionApiException, AccountApiException, CatalogApiException {
            if (operationResponse.getStatus() != Status.OK.getStatusCode()) {
                return operationResponse;
            }
            return getEntitlement(subscriptionId, new AuditMode(AuditLevel.NONE.toString()), request);
        }
    };
    final EntitlementCallCompletion<Response> callCompletionCreation = new EntitlementCallCompletion<Response>();
    return callCompletionCreation.withSynchronization(callback, timeoutSec, callCompletion, callContext);
}
Also used : Account(org.killbill.billing.account.api.Account) BillingActionPolicy(org.killbill.billing.catalog.api.BillingActionPolicy) CallContext(org.killbill.billing.util.callcontext.CallContext) LocalDate(org.joda.time.LocalDate) Response(javax.ws.rs.core.Response) ApiResponse(io.swagger.annotations.ApiResponse) PluginProperty(org.killbill.billing.payment.api.PluginProperty) UUID(java.util.UUID) Entitlement(org.killbill.billing.entitlement.api.Entitlement) PlanSpecifier(org.killbill.billing.catalog.api.PlanSpecifier) PlanPhasePriceOverride(org.killbill.billing.catalog.api.PlanPhasePriceOverride) Path(javax.ws.rs.Path) TimedResource(org.killbill.commons.metrics.TimedResource) Produces(javax.ws.rs.Produces) Consumes(javax.ws.rs.Consumes) ApiOperation(io.swagger.annotations.ApiOperation) PUT(javax.ws.rs.PUT) ApiResponses(io.swagger.annotations.ApiResponses)

Example 4 with BillingActionPolicy

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

the class OverdueStateApplicator method cancelSubscriptionsIfRequired.

private void cancelSubscriptionsIfRequired(final DateTime effectiveDate, final ImmutableAccountData account, final OverdueState nextOverdueState, final InternalCallContext context) throws OverdueException {
    if (nextOverdueState.getOverdueCancellationPolicy() == OverdueCancellationPolicy.NONE) {
        return;
    }
    final CallContext callContext = internalCallContextFactory.createCallContext(context);
    try {
        final BillingActionPolicy actionPolicy;
        switch(nextOverdueState.getOverdueCancellationPolicy()) {
            case END_OF_TERM:
                actionPolicy = BillingActionPolicy.END_OF_TERM;
                break;
            case IMMEDIATE:
                actionPolicy = BillingActionPolicy.IMMEDIATE;
                break;
            default:
                throw new IllegalStateException("Unexpected OverdueCancellationPolicy " + nextOverdueState.getOverdueCancellationPolicy());
        }
        final List<Entitlement> toBeCancelled = new LinkedList<Entitlement>();
        computeEntitlementsToCancel(account, toBeCancelled, callContext);
        try {
            entitlementInternalApi.cancel(toBeCancelled, context.toLocalDate(effectiveDate), actionPolicy, ImmutableList.<PluginProperty>of(), context);
        } catch (final EntitlementApiException e) {
            throw new OverdueException(e);
        }
    } catch (final EntitlementApiException e) {
        throw new OverdueException(e);
    }
}
Also used : BillingActionPolicy(org.killbill.billing.catalog.api.BillingActionPolicy) EntitlementApiException(org.killbill.billing.entitlement.api.EntitlementApiException) OverdueException(org.killbill.billing.overdue.config.api.OverdueException) Entitlement(org.killbill.billing.entitlement.api.Entitlement) CallContext(org.killbill.billing.util.callcontext.CallContext) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) LinkedList(java.util.LinkedList)

Example 5 with BillingActionPolicy

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

the class SubscriptionApiBase method populateDryRunEvents.

private void populateDryRunEvents(@Nullable final UUID bundleId, @Nullable final DryRunArguments dryRunArguments, final Collection<SubscriptionBaseEvent> outputDryRunEvents, final Collection<DefaultSubscriptionBase> outputSubscriptions, final SubscriptionCatalog catalog, final AddonUtils addonUtils, final TenantContext tenantContext, final InternalTenantContext context) throws SubscriptionBaseApiException, CatalogApiException {
    if (dryRunArguments == null || dryRunArguments.getAction() == null) {
        return;
    }
    final DateTime utcNow = clock.getUTCNow();
    List<SubscriptionBaseEvent> dryRunEvents = null;
    final EntitlementSpecifier entitlementSpecifier = dryRunArguments.getEntitlementSpecifier();
    final PlanPhaseSpecifier inputSpec = entitlementSpecifier.getPlanPhaseSpecifier();
    final boolean isInputSpecNullOrEmpty = inputSpec == null || (inputSpec.getPlanName() == null && inputSpec.getProductName() == null && inputSpec.getBillingPeriod() == null);
    // Create an overridesWithContext with a null context to indicate this is dryRun and no price overridden plan should be created.
    final PlanPhasePriceOverridesWithCallContext overridesWithContext = new DefaultPlanPhasePriceOverridesWithCallContext(entitlementSpecifier.getOverrides(), null);
    final LocalDate dryRunEffDt = dryRunArguments.getEffectiveDate();
    // EffectiveDate for the event is LocalDate but Catalog effectiveDate is a DateTime, so to maximize the chance of finding 'a' version
    // on that date we take the time closer to midnight - if 2 versions where uploaded on the same LocalDate this is returns the latest one.
    final DateTime catalogTargetDt = dryRunEffDt != null ? dryRunEffDt.toDateTimeAtStartOfDay(DateTimeZone.UTC).plusDays(1).minusSeconds(1) : utcNow;
    final StaticCatalog staticCatalog = catalog.versionForDate(catalogTargetDt);
    final Plan plan = isInputSpecNullOrEmpty ? null : staticCatalog.createOrFindPlan(inputSpec, overridesWithContext);
    switch(dryRunArguments.getAction()) {
        case START_BILLING:
            final SubscriptionBase baseSubscription = dao.getBaseSubscription(bundleId, catalog, context);
            final DateTime startEffectiveDate = dryRunEffDt != null ? context.toUTCDateTime(dryRunEffDt) : utcNow;
            final DateTime bundleStartDate = getBundleStartDateWithSanity(bundleId, baseSubscription, plan, startEffectiveDate, addonUtils, context);
            final UUID subscriptionId = UUIDs.randomUUID();
            dryRunEvents = apiService.getEventsOnCreation(subscriptionId, startEffectiveDate, bundleStartDate, plan, inputSpec.getPhaseType(), plan.getPriceList().getName(), startEffectiveDate, entitlementSpecifier.getBillCycleDay(), catalog, 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(), catalog, context);
            DateTime changeEffectiveDate = getDryRunEffectiveDate(dryRunEffDt, subscriptionForChange, context);
            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.getEffectiveDateForPolicy(policy, null, -1, context);
            }
            dryRunEvents = apiService.getEventsOnChangePlan(subscriptionForChange, plan, plan.getPriceList().getName(), changeEffectiveDate, true, entitlementSpecifier.getBillCycleDay(), catalog, context);
            break;
        case STOP_BILLING:
            final DefaultSubscriptionBase subscriptionForCancellation = (DefaultSubscriptionBase) dao.getSubscriptionFromId(dryRunArguments.getSubscriptionId(), catalog, context);
            DateTime cancelEffectiveDate = getDryRunEffectiveDate(dryRunEffDt, subscriptionForCancellation, context);
            if (dryRunEffDt == null) {
                BillingActionPolicy policy = dryRunArguments.getBillingActionPolicy();
                if (policy == null) {
                    final Plan currentPlan = subscriptionForCancellation.getCurrentPlan();
                    final PlanPhaseSpecifier spec = new PlanPhaseSpecifier(currentPlan.getName(), subscriptionForCancellation.getCurrentPhase().getPhaseType());
                    policy = catalog.planCancelPolicy(spec, clock.getUTCNow(), subscriptionForCancellation.getStartDate());
                }
                // 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.getEffectiveDateForPolicy(policy, null, -1, context);
            }
            dryRunEvents = apiService.getEventsOnCancelPlan(subscriptionForCancellation, cancelEffectiveDate, true, catalog, context);
            break;
        default:
            throw new IllegalArgumentException("Unexpected dryRunArguments action " + dryRunArguments.getAction());
    }
    if (dryRunEvents != null && !dryRunEvents.isEmpty()) {
        outputDryRunEvents.addAll(dryRunEvents);
    }
}
Also used : PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) BillingActionPolicy(org.killbill.billing.catalog.api.BillingActionPolicy) PlanChangeResult(org.killbill.billing.catalog.api.PlanChangeResult) SubscriptionBuilder(org.killbill.billing.subscription.api.user.SubscriptionBuilder) Plan(org.killbill.billing.catalog.api.Plan) LocalDate(org.joda.time.LocalDate) StaticCatalog(org.killbill.billing.catalog.api.StaticCatalog) DateTime(org.joda.time.DateTime) DefaultPlanPhasePriceOverridesWithCallContext(org.killbill.billing.subscription.api.svcs.DefaultPlanPhasePriceOverridesWithCallContext) EntitlementSpecifier(org.killbill.billing.entitlement.api.EntitlementSpecifier) DefaultSubscriptionBase(org.killbill.billing.subscription.api.user.DefaultSubscriptionBase) PlanPhasePriceOverridesWithCallContext(org.killbill.billing.catalog.api.PlanPhasePriceOverridesWithCallContext) DefaultPlanPhasePriceOverridesWithCallContext(org.killbill.billing.subscription.api.svcs.DefaultPlanPhasePriceOverridesWithCallContext) DefaultSubscriptionBase(org.killbill.billing.subscription.api.user.DefaultSubscriptionBase) UUID(java.util.UUID) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent)

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