Search in sources :

Example 1 with PlanChangeResult

use of org.killbill.billing.catalog.api.PlanChangeResult 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 PlanChangeResult

use of org.killbill.billing.catalog.api.PlanChangeResult 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 3 with PlanChangeResult

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

the class TestPlanRules method testExistingPriceListIsKept.

@Test(groups = "fast")
public void testExistingPriceListIsKept() throws CatalogApiException {
    final DefaultProduct product1 = cat.getCurrentProduct(0);
    final DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
    final PlanPhaseSpecifier from = new PlanPhaseSpecifier(product1.getName(), BillingPeriod.MONTHLY, priceList1.getName(), PhaseType.EVERGREEN);
    final PlanSpecifier to = new PlanSpecifier(product1.getName(), BillingPeriod.ANNUAL, priceList1.getName());
    PlanChangeResult result = null;
    try {
        result = cat.getPlanRules().planChange(from, to, cat);
    } catch (IllegalPlanChange e) {
        Assert.fail("We should not have triggered this error");
    } catch (CatalogApiException e) {
        Assert.fail("", e);
    }
    Assert.assertEquals(result.getPolicy(), BillingActionPolicy.END_OF_TERM);
    Assert.assertEquals(result.getAlignment(), PlanAlignmentChange.START_OF_SUBSCRIPTION);
    Assert.assertEquals(result.getNewPriceList(), priceList1);
}
Also used : PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) IllegalPlanChange(org.killbill.billing.catalog.api.IllegalPlanChange) DefaultProduct(org.killbill.billing.catalog.DefaultProduct) DefaultPriceList(org.killbill.billing.catalog.DefaultPriceList) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) PlanChangeResult(org.killbill.billing.catalog.api.PlanChangeResult) PlanSpecifier(org.killbill.billing.catalog.api.PlanSpecifier) Test(org.testng.annotations.Test)

Example 4 with PlanChangeResult

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

the class TestPlanRules method testBaseCase.

@Test(groups = "fast")
public void testBaseCase() throws CatalogApiException {
    final DefaultProduct product1 = cat.getCurrentProduct(0);
    final DefaultProduct product2 = cat.getCurrentProduct(1);
    final DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
    final DefaultPriceList priceList2 = cat.getPriceLists().getChildPriceLists()[0];
    final PlanPhaseSpecifier from = new PlanPhaseSpecifier(product1.getName(), BillingPeriod.MONTHLY, priceList1.getName(), PhaseType.EVERGREEN);
    final PlanSpecifier to = new PlanSpecifier(product2.getName(), BillingPeriod.MONTHLY, null);
    PlanChangeResult result = null;
    try {
        result = cat.getPlanRules().planChange(from, to, cat);
    } catch (IllegalPlanChange e) {
        Assert.fail("We should not have triggered this error");
    } catch (CatalogApiException e) {
        Assert.fail("", e);
    }
    Assert.assertEquals(result.getPolicy(), BillingActionPolicy.END_OF_TERM);
    Assert.assertEquals(result.getAlignment(), PlanAlignmentChange.START_OF_SUBSCRIPTION);
    Assert.assertEquals(result.getNewPriceList(), priceList2);
}
Also used : PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) IllegalPlanChange(org.killbill.billing.catalog.api.IllegalPlanChange) DefaultProduct(org.killbill.billing.catalog.DefaultProduct) DefaultPriceList(org.killbill.billing.catalog.DefaultPriceList) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) PlanChangeResult(org.killbill.billing.catalog.api.PlanChangeResult) PlanSpecifier(org.killbill.billing.catalog.api.PlanSpecifier) Test(org.testng.annotations.Test)

Example 5 with PlanChangeResult

use of org.killbill.billing.catalog.api.PlanChangeResult 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)

Aggregations

PlanChangeResult (org.killbill.billing.catalog.api.PlanChangeResult)7 CatalogApiException (org.killbill.billing.catalog.api.CatalogApiException)5 PlanPhaseSpecifier (org.killbill.billing.catalog.api.PlanPhaseSpecifier)4 DateTime (org.joda.time.DateTime)3 DefaultPriceList (org.killbill.billing.catalog.DefaultPriceList)3 BillingActionPolicy (org.killbill.billing.catalog.api.BillingActionPolicy)3 IllegalPlanChange (org.killbill.billing.catalog.api.IllegalPlanChange)3 PlanPhasePriceOverride (org.killbill.billing.catalog.api.PlanPhasePriceOverride)3 PlanSpecifier (org.killbill.billing.catalog.api.PlanSpecifier)3 InternalTenantContext (org.killbill.billing.callcontext.InternalTenantContext)2 DefaultProduct (org.killbill.billing.catalog.DefaultProduct)2 Plan (org.killbill.billing.catalog.api.Plan)2 Test (org.testng.annotations.Test)2 UUID (java.util.UUID)1 Catalog (org.killbill.billing.catalog.api.Catalog)1 PlanAlignmentChange (org.killbill.billing.catalog.api.PlanAlignmentChange)1 PlanPhasePriceOverridesWithCallContext (org.killbill.billing.catalog.api.PlanPhasePriceOverridesWithCallContext)1 DefaultSubscriptionBase (org.killbill.billing.subscription.api.user.DefaultSubscriptionBase)1 SubscriptionBaseApiException (org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)1 SubscriptionBuilder (org.killbill.billing.subscription.api.user.SubscriptionBuilder)1