use of org.killbill.billing.catalog.api.PhaseType 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.catalog.api.PhaseType in project killbill by killbill.
the class DefaultSubscriptionBaseApiService method doChangePlan.
private void doChangePlan(final DefaultSubscriptionBase subscription, final PlanSpecifier spec, final List<PlanPhasePriceOverride> overrides, final DateTime effectiveDate, final CallContext context) throws SubscriptionBaseApiException, CatalogApiException {
final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
final PlanPhasePriceOverridesWithCallContext overridesWithContext = new DefaultPlanPhasePriceOverridesWithCallContext(overrides, context);
final Plan newPlan = catalogService.getFullCatalog(true, true, internalCallContext).createOrFindPlan(spec, overridesWithContext, effectiveDate, subscription.getStartDate());
final PhaseType initialPhaseType;
if (overrides != null && overrides.size() == 1 && overrides.get(0).getPlanPhaseSpecifier() != null && overrides.get(0).getCurrency() == null) {
initialPhaseType = overrides.get(0).getPlanPhaseSpecifier().getPhaseType();
} else {
initialPhaseType = null;
}
if (ProductCategory.ADD_ON.toString().equalsIgnoreCase(newPlan.getProduct().getCategory().toString())) {
if (newPlan.getPlansAllowedInBundle() != -1 && newPlan.getPlansAllowedInBundle() > 0 && addonUtils.countExistingAddOnsWithSamePlanName(dao.getSubscriptions(subscription.getBundleId(), null, internalCallContext), newPlan.getName()) >= newPlan.getPlansAllowedInBundle()) {
// the plan can be changed to the new value, because it has reached its limit by bundle
throw new SubscriptionBaseApiException(ErrorCode.SUB_CHANGE_AO_MAX_PLAN_ALLOWED_BY_BUNDLE, newPlan.getName());
}
}
if (newPlan.getProduct().getCategory() != subscription.getCategory()) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_CHANGE_INVALID, subscription.getId());
}
final List<DefaultSubscriptionBase> addOnSubscriptionsToBeCancelled = new ArrayList<DefaultSubscriptionBase>();
final List<SubscriptionBaseEvent> addOnCancelEvents = new ArrayList<SubscriptionBaseEvent>();
final List<SubscriptionBaseEvent> changeEvents = getEventsOnChangePlan(subscription, newPlan, newPlan.getPriceListName(), effectiveDate, true, addOnSubscriptionsToBeCancelled, addOnCancelEvents, initialPhaseType, internalCallContext);
dao.changePlan(subscription, changeEvents, addOnSubscriptionsToBeCancelled, addOnCancelEvents, internalCallContext);
final Catalog fullCatalog = catalogService.getFullCatalog(true, true, internalCallContext);
subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId(), internalCallContext), fullCatalog);
}
use of org.killbill.billing.catalog.api.PhaseType in project killbill by killbill.
the class EventsStreamBuilder method createPlanPhaseSpecifier.
private PlanPhaseSpecifier createPlanPhaseSpecifier(final SubscriptionBase subscription) {
final String planName;
final PhaseType phaseType;
if (subscription.getState() == EntitlementState.PENDING) {
final SubscriptionBaseTransition transition = subscription.getPendingTransition();
planName = transition.getNextPlan().getName();
phaseType = transition.getNextPhase().getPhaseType();
} else {
planName = subscription.getLastActivePlan().getName();
phaseType = subscription.getLastActivePhase().getPhaseType();
}
return new PlanPhaseSpecifier(planName, phaseType);
}
use of org.killbill.billing.catalog.api.PhaseType in project killbill by killbill.
the class SubscriptionResourceHelpers method buildPlanPhasePriceOverride.
private static PlanPhasePriceOverride buildPlanPhasePriceOverride(final PlanSpecifier spec, final Currency currency, final PhasePriceJson input, final List<UsagePriceOverride> usagePrices) {
if (input.getPhaseName() != null) {
return new PlanPhasePriceOverride() {
@Override
public String getPhaseName() {
return input.getPhaseName();
}
@Override
public PlanPhaseSpecifier getPlanPhaseSpecifier() {
return null;
}
@Override
public Currency getCurrency() {
return currency;
}
@Override
public BigDecimal getFixedPrice() {
return input.getFixedPrice();
}
@Override
public BigDecimal getRecurringPrice() {
return input.getRecurringPrice();
}
@Override
public List<UsagePriceOverride> getUsagePriceOverrides() {
return usagePrices;
}
};
}
final PhaseType phaseType = input.getPhaseType() != null ? PhaseType.valueOf(input.getPhaseType()) : null;
final PlanPhaseSpecifier planPhaseSpecifier = spec.getPlanName() != null ? new PlanPhaseSpecifier(spec.getPlanName(), phaseType) : new PlanPhaseSpecifier(spec.getProductName(), spec.getBillingPeriod(), spec.getPriceListName(), phaseType);
final Currency resolvedCurrency = input.getFixedPrice() != null || input.getRecurringPrice() != null ? currency : null;
return new PlanPhasePriceOverride() {
@Override
public String getPhaseName() {
return null;
}
@Override
public PlanPhaseSpecifier getPlanPhaseSpecifier() {
return planPhaseSpecifier;
}
@Override
public Currency getCurrency() {
return resolvedCurrency;
}
@Override
public BigDecimal getFixedPrice() {
return input.getFixedPrice();
}
@Override
public BigDecimal getRecurringPrice() {
return input.getRecurringPrice();
}
@Override
public List<UsagePriceOverride> getUsagePriceOverrides() {
return usagePrices;
}
};
}
use of org.killbill.billing.catalog.api.PhaseType in project killbill by killbill.
the class DefaultSubscriptionBaseApiService method doChangePlan.
private void doChangePlan(final DefaultSubscriptionBase subscription, final EntitlementSpecifier spec, final DateTime effectiveDate, final CallContext context) throws SubscriptionBaseApiException, CatalogApiException {
final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
final PlanPhasePriceOverridesWithCallContext overridesWithContext = new DefaultPlanPhasePriceOverridesWithCallContext(spec.getOverrides(), context);
final SubscriptionCatalog catalog = subscriptionCatalogApi.getFullCatalog(internalCallContext);
final PlanPhaseSpecifier planPhaseSpecifier = spec.getPlanPhaseSpecifier();
final StaticCatalog versionCatalog = catalog.versionForDate(effectiveDate);
final Plan newPlan = versionCatalog.createOrFindPlan(planPhaseSpecifier, overridesWithContext);
final PhaseType initialPhaseType = planPhaseSpecifier.getPhaseType();
if (ProductCategory.ADD_ON.toString().equalsIgnoreCase(newPlan.getProduct().getCategory().toString())) {
if (newPlan.getPlansAllowedInBundle() != -1 && newPlan.getPlansAllowedInBundle() > 0 && addonUtils.countExistingAddOnsWithSamePlanName(dao.getSubscriptions(subscription.getBundleId(), null, catalog, internalCallContext), newPlan.getName()) >= newPlan.getPlansAllowedInBundle()) {
// the plan can be changed to the new value, because it has reached its limit by bundle
throw new SubscriptionBaseApiException(ErrorCode.SUB_CHANGE_AO_MAX_PLAN_ALLOWED_BY_BUNDLE, newPlan.getName());
}
}
if (newPlan.getProduct().getCategory() != subscription.getCategory()) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_CHANGE_INVALID, subscription.getId());
}
final List<DefaultSubscriptionBase> addOnSubscriptionsToBeCancelled = new ArrayList<DefaultSubscriptionBase>();
final List<SubscriptionBaseEvent> addOnCancelEvents = new ArrayList<SubscriptionBaseEvent>();
final List<SubscriptionBaseEvent> changeEvents = getEventsOnChangePlan(subscription, newPlan, newPlan.getPriceList().getName(), effectiveDate, true, addOnSubscriptionsToBeCancelled, addOnCancelEvents, initialPhaseType, spec.getBillCycleDay(), catalog, internalCallContext);
dao.changePlan(subscription, changeEvents, addOnSubscriptionsToBeCancelled, addOnCancelEvents, catalog, internalCallContext);
subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId(), internalCallContext), catalog);
}
Aggregations