use of org.killbill.billing.subscription.events.SubscriptionBaseEvent in project killbill by killbill.
the class DefaultSubscriptionBaseApiService method doCancelPlan.
private boolean doCancelPlan(final Map<DefaultSubscriptionBase, DateTime> subscriptions, final SubscriptionCatalog catalog, final InternalCallContext internalCallContext) throws SubscriptionBaseApiException {
final List<DefaultSubscriptionBase> subscriptionsToBeCancelled = new LinkedList<DefaultSubscriptionBase>();
final List<SubscriptionBaseEvent> cancelEvents = new LinkedList<SubscriptionBaseEvent>();
try {
for (final DefaultSubscriptionBase subscription : subscriptions.keySet()) {
final EntitlementState currentState = subscription.getState();
if (currentState == EntitlementState.CANCELLED) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_CANCEL_BAD_STATE, subscription.getId(), currentState);
}
final DateTime effectiveDate = subscriptions.get(subscription);
// If subscription was future cancelled at an earlier date we disallow the operation -- i.e,
// user should first uncancel prior trying to cancel again.
// However, note that in case a future cancellation already exists with a greater or equal effectiveDate,
// the operation is allowed, but such existing cancellation would become invalidated (is_active=0)
final SubscriptionBaseTransition pendingTransition = subscription.getPendingTransition();
if (pendingTransition != null && pendingTransition.getTransitionType() == SubscriptionBaseTransitionType.CANCEL && pendingTransition.getEffectiveTransitionTime().compareTo(effectiveDate) < 0) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_CANCEL_BAD_STATE, subscription.getId(), "PENDING CANCELLED");
}
validateEffectiveDate(subscription, effectiveDate);
subscriptionsToBeCancelled.add(subscription);
cancelEvents.addAll(getEventsOnCancelPlan(subscription, effectiveDate, false, catalog, internalCallContext));
if (subscription.getCategory() == ProductCategory.BASE) {
subscriptionsToBeCancelled.addAll(computeAddOnsToCancel(cancelEvents, null, subscription.getBundleId(), effectiveDate, catalog, internalCallContext));
}
}
dao.cancelSubscriptions(subscriptionsToBeCancelled, cancelEvents, catalog, internalCallContext);
boolean allSubscriptionsCancelled = true;
for (final DefaultSubscriptionBase subscription : subscriptions.keySet()) {
subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId(), internalCallContext), catalog);
allSubscriptionsCancelled = allSubscriptionsCancelled && (subscription.getState() == EntitlementState.CANCELLED);
}
return allSubscriptionsCancelled;
} catch (final CatalogApiException e) {
throw new SubscriptionBaseApiException(e);
}
}
use of org.killbill.billing.subscription.events.SubscriptionBaseEvent in project killbill by killbill.
the class DefaultSubscriptionBaseApiService method getEventsOnChangePlan.
private List<SubscriptionBaseEvent> getEventsOnChangePlan(final DefaultSubscriptionBase subscription, final Plan newPlan, final String newPriceList, final DateTime effectiveDate, final boolean addCancellationAddOnForEventsIfRequired, final Collection<DefaultSubscriptionBase> addOnSubscriptionsToBeCancelled, final Collection<SubscriptionBaseEvent> addOnCancelEvents, final PhaseType initialPhaseType, final Integer bcd, final SubscriptionCatalog catalog, final InternalTenantContext internalTenantContext) throws CatalogApiException, SubscriptionBaseApiException {
final TimedPhase currentTimedPhase = planAligner.getCurrentTimedPhaseOnChange(subscription, newPlan, effectiveDate, initialPhaseType, catalog, internalTenantContext);
validateSubscriptionStateForChangePlan(subscription, effectiveDate);
final SubscriptionBaseEvent changeEvent = new ApiEventChange(new ApiEventBuilder().setSubscriptionId(subscription.getId()).setEventPlan(newPlan.getName()).setEventPlanPhase(currentTimedPhase.getPhase().getName()).setEventPriceList(newPriceList).setEffectiveDate(effectiveDate).setFromDisk(true));
final TimedPhase nextTimedPhase = planAligner.getNextTimedPhaseOnChange(subscription, newPlan, effectiveDate, initialPhaseType, catalog, internalTenantContext);
final PhaseEvent nextPhaseEvent = (nextTimedPhase != null) ? PhaseEventData.createNextPhaseEvent(subscription.getId(), nextTimedPhase.getPhase().getName(), nextTimedPhase.getStartPhase()) : null;
final List<SubscriptionBaseEvent> changeEvents = new ArrayList<SubscriptionBaseEvent>();
// Only add the PHASE if it does not coincide with the CHANGE, if not this is 'just' a CHANGE.
changeEvents.add(changeEvent);
if (bcd != null) {
final SubscriptionBaseEvent bcdEvent = new BCDEventData(new BCDEventBuilder().setSubscriptionId(subscription.getId()).setEffectiveDate(effectiveDate).setActive(true).setBillCycleDayLocal(bcd));
changeEvents.add(bcdEvent);
}
if (nextPhaseEvent != null && !nextPhaseEvent.getEffectiveDate().equals(changeEvent.getEffectiveDate())) {
changeEvents.add(nextPhaseEvent);
}
if (subscription.getCategory() == ProductCategory.BASE && addCancellationAddOnForEventsIfRequired) {
final Product currentBaseProduct = changeEvent.getEffectiveDate().compareTo(clock.getUTCNow()) <= 0 ? newPlan.getProduct() : subscription.getCurrentOrPendingPlan().getProduct();
addOnSubscriptionsToBeCancelled.addAll(addCancellationAddOnForEventsIfRequired(addOnCancelEvents, currentBaseProduct, subscription.getBundleId(), effectiveDate, catalog, internalTenantContext));
}
return changeEvents;
}
use of org.killbill.billing.subscription.events.SubscriptionBaseEvent in project killbill by killbill.
the class DefaultSubscriptionBaseApiService method getEventsOnCancelPlan.
@Override
public List<SubscriptionBaseEvent> getEventsOnCancelPlan(final DefaultSubscriptionBase subscription, final DateTime effectiveDate, final boolean addCancellationAddOnForEventsIfRequired, final SubscriptionCatalog fullCatalog, final InternalTenantContext internalTenantContext) throws CatalogApiException {
final List<SubscriptionBaseEvent> cancelEvents = new ArrayList<SubscriptionBaseEvent>();
final SubscriptionBaseEvent cancelEvent = new ApiEventCancel(new ApiEventBuilder().setSubscriptionId(subscription.getId()).setEffectiveDate(effectiveDate).setFromDisk(true));
cancelEvents.add(cancelEvent);
if (subscription.getCategory() == ProductCategory.BASE && addCancellationAddOnForEventsIfRequired) {
final Product currentBaseProduct = cancelEvent.getEffectiveDate().compareTo(clock.getUTCNow()) <= 0 ? null : subscription.getCurrentPlan().getProduct();
addCancellationAddOnForEventsIfRequired(cancelEvents, currentBaseProduct, subscription.getBundleId(), effectiveDate, fullCatalog, internalTenantContext);
}
return cancelEvents;
}
use of org.killbill.billing.subscription.events.SubscriptionBaseEvent in project killbill by killbill.
the class DefaultSubscriptionBaseApiService method handleBasePlanEvent.
@Override
public int handleBasePlanEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, final SubscriptionCatalog catalog, final CallContext context) throws CatalogApiException {
final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
if (((ApiEvent) event).getApiEventType() == ApiEventType.CANCEL || ((ApiEvent) event).getApiEventType() == ApiEventType.CHANGE) {
final Product baseProduct = (subscription.getState() == EntitlementState.CANCELLED) ? null : subscription.getCurrentPlan().getProduct();
final List<SubscriptionBaseEvent> cancelEvents = new LinkedList<SubscriptionBaseEvent>();
final List<DefaultSubscriptionBase> subscriptionsToBeCancelled = computeAddOnsToCancel(cancelEvents, baseProduct, subscription.getBundleId(), event.getEffectiveDate(), catalog, internalCallContext);
dao.cancelSubscriptionsOnBasePlanEvent(subscription, event, subscriptionsToBeCancelled, cancelEvents, catalog, internalCallContext);
return subscriptionsToBeCancelled.size();
} else {
dao.notifyOnBasePlanEvent(subscription, event, catalog, internalCallContext);
return 0;
}
}
use of org.killbill.billing.subscription.events.SubscriptionBaseEvent in project killbill by killbill.
the class DefaultSubscriptionBaseApiService method createEvents.
private void createEvents(final Iterable<SubscriptionSpecifier> subscriptions, final CallContext context, final Map<UUID, List<SubscriptionBaseEvent>> eventsMap, final Collection<SubscriptionBase> subscriptionBaseList, final SubscriptionCatalog catalog) throws SubscriptionBaseApiException {
for (final SubscriptionSpecifier subscription : subscriptions) {
try {
final DefaultSubscriptionBase subscriptionBase = new DefaultSubscriptionBase(subscription.getBuilder(), this, clock);
final InternalCallContext internalCallContext = createCallContextFromBundleId(subscriptionBase.getBundleId(), context);
final List<SubscriptionBaseEvent> events = getEventsOnCreation(subscriptionBase.getId(), subscriptionBase.getAlignStartDate(), subscriptionBase.getBundleStartDate(), subscription.getPlan(), subscription.getInitialPhase(), subscription.getRealPriceList(), subscription.getEffectiveDate(), subscription.getBuilder().getSubscriptionBCD(), catalog, internalCallContext);
eventsMap.put(subscriptionBase.getId(), events);
subscriptionBaseList.add(subscriptionBase);
} catch (final CatalogApiException e) {
throw new SubscriptionBaseApiException(e);
}
}
}
Aggregations