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);
}
}
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;
}
}
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);
}
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);
}
}
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;
}
}
Aggregations