use of org.killbill.billing.subscription.exceptions.SubscriptionBaseError in project killbill by killbill.
the class AddonUtils method isAddonIncludedFromPlanName.
public boolean isAddonIncludedFromPlanName(final String basePlanName, final Plan targetAddOnPlan, final DateTime requestedDate, final InternalTenantContext context) {
try {
final Plan plan = catalogService.getFullCatalog(true, true, context).findPlan(basePlanName, requestedDate);
final Product product = plan.getProduct();
return isAddonIncluded(product, targetAddOnPlan);
} catch (CatalogApiException e) {
throw new SubscriptionBaseError(e);
}
}
use of org.killbill.billing.subscription.exceptions.SubscriptionBaseError in project killbill by killbill.
the class PlanAligner method getTimedPhaseOnCreate.
private List<TimedPhase> getTimedPhaseOnCreate(final DateTime subscriptionStartDate, final DateTime bundleStartDate, final Plan plan, @Nullable final PhaseType initialPhase, final DateTime effectiveDate, final InternalTenantContext context) throws CatalogApiException, SubscriptionBaseApiException {
final Catalog catalog = catalogService.getFullCatalog(true, true, context);
final PlanSpecifier planSpecifier = new PlanSpecifier(plan.getName());
final DateTime planStartDate;
final PlanAlignmentCreate alignment = catalog.planCreateAlignment(planSpecifier, effectiveDate);
switch(alignment) {
case START_OF_SUBSCRIPTION:
planStartDate = subscriptionStartDate;
break;
case START_OF_BUNDLE:
planStartDate = bundleStartDate;
break;
default:
throw new SubscriptionBaseError(String.format("Unknown PlanAlignmentCreate %s", alignment));
}
return getPhaseAlignments(plan, initialPhase, planStartDate);
}
use of org.killbill.billing.subscription.exceptions.SubscriptionBaseError in project killbill by killbill.
the class PlanAligner method getTimedPhaseOnChange.
private TimedPhase getTimedPhaseOnChange(final DateTime subscriptionStartDate, final DateTime bundleStartDate, final PlanPhase currentPhase, final Plan currentPlan, final Plan nextPlan, final DateTime effectiveDate, final DateTime lastOrCurrentChangeEffectiveDate, final PhaseType originalInitialPhase, @Nullable final PhaseType newPlanInitialPhaseType, final WhichPhase which, final InternalTenantContext context) throws CatalogApiException, SubscriptionBaseApiException {
final Catalog catalog = catalogService.getFullCatalog(true, true, context);
final PlanPhaseSpecifier fromPlanPhaseSpecifier = new PlanPhaseSpecifier(currentPlan.getName(), currentPhase.getPhaseType());
final PlanSpecifier toPlanSpecifier = new PlanSpecifier(nextPlan.getName());
final PhaseType initialPhase;
final DateTime planStartDate;
final PlanAlignmentChange alignment = catalog.planChangeAlignment(fromPlanPhaseSpecifier, toPlanSpecifier, effectiveDate);
switch(alignment) {
case START_OF_SUBSCRIPTION:
planStartDate = subscriptionStartDate;
initialPhase = newPlanInitialPhaseType != null ? newPlanInitialPhaseType : (isPlanContainPhaseType(nextPlan, originalInitialPhase) ? originalInitialPhase : null);
break;
case START_OF_BUNDLE:
planStartDate = bundleStartDate;
initialPhase = newPlanInitialPhaseType != null ? newPlanInitialPhaseType : (isPlanContainPhaseType(nextPlan, originalInitialPhase) ? originalInitialPhase : null);
break;
case CHANGE_OF_PLAN:
planStartDate = lastOrCurrentChangeEffectiveDate;
initialPhase = newPlanInitialPhaseType;
break;
case CHANGE_OF_PRICELIST:
throw new SubscriptionBaseError(String.format("Not implemented yet %s", alignment));
default:
throw new SubscriptionBaseError(String.format("Unknown PlanAlignmentChange %s", alignment));
}
final List<TimedPhase> timedPhases = getPhaseAlignments(nextPlan, initialPhase, planStartDate);
return getTimedPhase(timedPhases, effectiveDate, which);
}
use of org.killbill.billing.subscription.exceptions.SubscriptionBaseError in project killbill by killbill.
the class PlanAligner method getPhaseAlignments.
private List<TimedPhase> getPhaseAlignments(final Plan plan, @Nullable final PhaseType initialPhase, final DateTime initialPhaseStartDate) throws SubscriptionBaseApiException {
if (plan == null) {
return Collections.emptyList();
}
final List<TimedPhase> result = new LinkedList<TimedPhase>();
DateTime curPhaseStart = (initialPhase == null) ? initialPhaseStartDate : null;
DateTime nextPhaseStart;
for (final PlanPhase cur : plan.getAllPhases()) {
// For create we can specify the phase so skip any phase until we reach initialPhase
if (curPhaseStart == null) {
if (initialPhase != cur.getPhaseType()) {
continue;
}
curPhaseStart = initialPhaseStartDate;
}
result.add(new TimedPhase(cur, curPhaseStart));
// STEPH check for duration null instead TimeUnit UNLIMITED
if (cur.getPhaseType() != PhaseType.EVERGREEN) {
final Duration curPhaseDuration = cur.getDuration();
nextPhaseStart = addDuration(curPhaseStart, curPhaseDuration);
if (nextPhaseStart == null) {
throw new SubscriptionBaseError(String.format("Unexpected non ending UNLIMITED phase for plan %s", plan.getName()));
}
curPhaseStart = nextPhaseStart;
}
}
if (initialPhase != null && curPhaseStart == null) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_BAD_PHASE, initialPhase);
}
return result;
}
use of org.killbill.billing.subscription.exceptions.SubscriptionBaseError in project killbill by killbill.
the class DefaultSubscriptionInternalApi method createSubscription.
@Override
public SubscriptionBase createSubscription(final UUID bundleId, final PlanPhaseSpecifier spec, final List<PlanPhasePriceOverride> overrides, final DateTime requestedDateWithMs, final boolean isMigrated, final InternalCallContext context) throws SubscriptionBaseApiException {
try {
final DateTime now = clock.getUTCNow();
final DateTime effectiveDate = (requestedDateWithMs != null) ? DefaultClock.truncateMs(requestedDateWithMs) : now;
/*
if (requestedDate.isAfter(now)) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_INVALID_REQUESTED_DATE, now.toString(), requestedDate.toString());
}
*/
final CallContext callContext = internalCallContextFactory.createCallContext(context);
final Catalog catalog = catalogService.getFullCatalog(true, true, context);
final PlanPhasePriceOverridesWithCallContext overridesWithContext = new DefaultPlanPhasePriceOverridesWithCallContext(overrides, callContext);
final Plan plan = catalog.createOrFindPlan(spec, overridesWithContext, effectiveDate);
final PlanPhase phase = plan.getAllPhases()[0];
if (phase == null) {
throw new SubscriptionBaseError(String.format("No initial PlanPhase for Product %s, term %s and set %s does not exist in the catalog", spec.getProductName(), spec.getBillingPeriod().toString(), plan.getPriceListName()));
}
final SubscriptionBaseBundle bundle = dao.getSubscriptionBundleFromId(bundleId, context);
if (bundle == null) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_NO_BUNDLE, bundleId);
}
final DefaultSubscriptionBase baseSubscription = (DefaultSubscriptionBase) dao.getBaseSubscription(bundleId, context);
// verify the number of subscriptions (of the same kind) allowed per bundle
if (ProductCategory.ADD_ON.toString().equalsIgnoreCase(plan.getProduct().getCategory().toString())) {
if (plan.getPlansAllowedInBundle() != -1 && plan.getPlansAllowedInBundle() > 0 && addonUtils.countExistingAddOnsWithSamePlanName(getSubscriptionsForBundle(bundleId, null, context), plan.getName()) >= plan.getPlansAllowedInBundle()) {
// a new ADD_ON subscription of the same plan can't be added because it has reached its limit by bundle
throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_AO_MAX_PLAN_ALLOWED_BY_BUNDLE, plan.getName());
}
}
final DateTime bundleStartDate = getBundleStartDateWithSanity(bundleId, baseSubscription, plan, effectiveDate, context);
return apiService.createPlan(new SubscriptionBuilder().setId(UUIDs.randomUUID()).setBundleId(bundleId).setBundleExternalKey(bundle.getExternalKey()).setCategory(plan.getProduct().getCategory()).setBundleStartDate(bundleStartDate).setAlignStartDate(effectiveDate).setMigrated(isMigrated), plan, spec.getPhaseType(), plan.getPriceListName(), effectiveDate, now, callContext);
} catch (final CatalogApiException e) {
throw new SubscriptionBaseApiException(e);
}
}
Aggregations