use of org.killbill.billing.subscription.events.phase.PhaseEvent in project killbill by killbill.
the class DefaultSubscriptionBaseTimeline method toExistingEvents.
private List<ExistingEvent> toExistingEvents(final SubscriptionCatalog catalog, final ProductCategory category, final List<SubscriptionBaseEvent> events) throws CatalogApiException {
final List<ExistingEvent> result = new LinkedList<SubscriptionBaseTimeline.ExistingEvent>();
Plan prevPlan = null;
String prevProductName = null;
String prevPriceListName = null;
PhaseType prevPhaseType = null;
DateTime startDate = null;
for (final SubscriptionBaseEvent cur : events) {
if (!cur.isActive()) {
continue;
}
startDate = (startDate == null) ? cur.getEffectiveDate() : startDate;
String productName = null;
String priceListName = null;
PhaseType phaseType = null;
Plan plan = null;
String planPhaseName = null;
Integer billCycleDayLocal = null;
ApiEventType apiType = null;
switch(cur.getType()) {
case PHASE:
final PhaseEvent phaseEV = (PhaseEvent) cur;
planPhaseName = phaseEV.getPhase();
// A PHASE event always occurs within the same plan (and is never the first event)
phaseType = prevPlan != null ? prevPlan.findPhase(phaseEV.getPhase()).getPhaseType() : null;
plan = prevPlan;
productName = prevProductName;
priceListName = prevPriceListName;
break;
case BCD_UPDATE:
final BCDEvent bcdEvent = (BCDEvent) cur;
billCycleDayLocal = bcdEvent.getBillCycleDayLocal();
break;
case API_USER:
final ApiEvent userEV = (ApiEvent) cur;
apiType = userEV.getApiEventType();
planPhaseName = userEV.getEventPlanPhase();
plan = (userEV.getEventPlan() != null) ? catalog.findPlan(userEV.getEventPlan(), cur.getEffectiveDate(), startDate) : null;
phaseType = (plan != null && userEV.getEventPlanPhase() != null) ? plan.findPhase(userEV.getEventPlanPhase()).getPhaseType() : prevPhaseType;
productName = (plan != null) ? plan.getProduct().getName() : prevProductName;
priceListName = (userEV.getPriceList() != null) ? userEV.getPriceList() : prevPriceListName;
break;
}
final SubscriptionBaseTransitionType transitionType = SubscriptionBaseTransitionData.toSubscriptionTransitionType(cur.getType(), apiType);
final String planNameWithClosure = plan != null ? plan.getName() : null;
final String planPhaseNameWithClosure = planPhaseName;
final Integer billCycleDayLocalWithClosure = billCycleDayLocal;
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier(planNameWithClosure, phaseType);
result.add(new ExistingEvent() {
@Override
public SubscriptionBaseTransitionType getSubscriptionTransitionType() {
return transitionType;
}
@Override
public ProductCategory getProductCategory() {
return category;
}
@Override
public PlanPhaseSpecifier getPlanPhaseSpecifier() {
return spec;
}
@Override
public UUID getEventId() {
return cur.getId();
}
@Override
public DateTime getEffectiveDate() {
return cur.getEffectiveDate();
}
@Override
public String getPlanName() {
return planNameWithClosure;
}
@Override
public String getPlanPhaseName() {
return planPhaseNameWithClosure;
}
@Override
public Integer getBillCycleDayLocal() {
return billCycleDayLocalWithClosure;
}
});
prevPlan = plan;
prevProductName = productName;
prevPriceListName = priceListName;
prevPhaseType = phaseType;
}
sortExistingEvent(result);
return result;
}
use of org.killbill.billing.subscription.events.phase.PhaseEvent in project killbill by killbill.
the class DefaultSubscriptionBaseApiService method uncancel.
@Override
public boolean uncancel(final DefaultSubscriptionBase subscription, final CallContext context) throws SubscriptionBaseApiException {
if (!subscription.isFutureCancelled()) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_UNCANCEL_BAD_STATE, subscription.getId().toString());
}
try {
final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
final SubscriptionCatalog catalog = subscriptionCatalogApi.getFullCatalog(internalCallContext);
final SubscriptionBaseEvent uncancelEvent = new ApiEventUncancel(new ApiEventBuilder().setSubscriptionId(subscription.getId()).setEffectiveDate(context.getCreatedDate()).setFromDisk(true));
final List<SubscriptionBaseEvent> uncancelEvents = new ArrayList<SubscriptionBaseEvent>();
uncancelEvents.add(uncancelEvent);
//
// Used to compute effective for next phase (which was set unactive during cancellation).
// In case of a pending subscription we don't want to pass an effective date prior the CREATE event as we would end up with the wrong
// transition in PlanAligner (next transition would be CREATE instead of potential next PHASE)
//
final DateTime planAlignerEffectiveDate = subscription.getState() == EntitlementState.PENDING ? subscription.getStartDate() : context.getCreatedDate();
final TimedPhase nextTimedPhase = planAligner.getNextTimedPhase(subscription, planAlignerEffectiveDate, catalog, internalCallContext);
final PhaseEvent nextPhaseEvent = (nextTimedPhase != null) ? PhaseEventData.createNextPhaseEvent(subscription.getId(), nextTimedPhase.getPhase().getName(), nextTimedPhase.getStartPhase()) : null;
if (nextPhaseEvent != null) {
uncancelEvents.add(nextPhaseEvent);
}
dao.uncancelSubscription(subscription, uncancelEvents, internalCallContext);
subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId(), internalCallContext), catalog);
return true;
} catch (final CatalogApiException e) {
throw new SubscriptionBaseApiException(e);
}
}
use of org.killbill.billing.subscription.events.phase.PhaseEvent in project killbill by killbill.
the class DefaultSubscriptionBaseApiService method undoChangePlan.
@Override
public boolean undoChangePlan(final DefaultSubscriptionBase subscription, final CallContext context) throws SubscriptionBaseApiException {
if (!subscription.isPendingChangePlan()) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_UNDO_CHANGE_BAD_STATE, subscription.getId().toString());
}
try {
final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
final SubscriptionCatalog catalog = subscriptionCatalogApi.getFullCatalog(internalCallContext);
final SubscriptionBaseEvent undoChangePlanEvent = new ApiEventUndoChange(new ApiEventBuilder().setSubscriptionId(subscription.getId()).setEffectiveDate(context.getCreatedDate()).setFromDisk(true));
final List<SubscriptionBaseEvent> undoChangePlanEvents = new ArrayList<SubscriptionBaseEvent>();
undoChangePlanEvents.add(undoChangePlanEvent);
//
// Used to compute effective for next phase (which was set unactive during cancellation).
// In case of a pending subscription we don't want to pass an effective date prior the CREATE event as we would end up with the wrong
// transition in PlanAligner (next transition would be CREATE instead of potential next PHASE)
//
final DateTime planAlignerEffectiveDate = subscription.getState() == EntitlementState.PENDING ? subscription.getStartDate() : context.getCreatedDate();
final TimedPhase nextTimedPhase = planAligner.getNextTimedPhase(subscription, planAlignerEffectiveDate, catalog, internalCallContext);
final PhaseEvent nextPhaseEvent = (nextTimedPhase != null) ? PhaseEventData.createNextPhaseEvent(subscription.getId(), nextTimedPhase.getPhase().getName(), nextTimedPhase.getStartPhase()) : null;
if (nextPhaseEvent != null) {
undoChangePlanEvents.add(nextPhaseEvent);
}
dao.undoChangePlan(subscription, undoChangePlanEvents, internalCallContext);
subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId(), internalCallContext), catalog);
return true;
} catch (final CatalogApiException e) {
throw new SubscriptionBaseApiException(e);
}
}
use of org.killbill.billing.subscription.events.phase.PhaseEvent in project killbill by killbill.
the class DefaultSubscriptionBaseService method onPhaseEvent.
private boolean onPhaseEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent readyPhaseEvent, final SubscriptionCatalog catalog, final InternalCallContext context) {
try {
final TimedPhase nextTimedPhase = planAligner.getNextTimedPhase(subscription, readyPhaseEvent.getEffectiveDate(), catalog, context);
final PhaseEvent nextPhaseEvent = (nextTimedPhase != null) ? PhaseEventData.createNextPhaseEvent(subscription.getId(), nextTimedPhase.getPhase().getName(), nextTimedPhase.getStartPhase()) : null;
if (nextPhaseEvent != null) {
dao.createNextPhaseEvent(subscription, readyPhaseEvent, nextPhaseEvent, context);
return true;
}
} catch (final SubscriptionBaseError e) {
log.warn("Error inserting next phase for subscriptionId='{}'", subscription.getId(), e);
}
return false;
}
use of org.killbill.billing.subscription.events.phase.PhaseEvent in project killbill by killbill.
the class TestSubscriptionHelper method checkNextPhaseChange.
public void checkNextPhaseChange(final DefaultSubscriptionBase subscription, final int expPendingEvents, final DateTime expPhaseChange) {
final List<SubscriptionBaseEvent> events = dao.getPendingEventsForSubscription(subscription.getId(), internalCallContext);
assertNotNull(events);
printEvents(events);
assertEquals(events.size(), expPendingEvents);
if (events.size() > 0 && expPhaseChange != null) {
boolean foundPhase = false;
boolean foundChange = false;
for (final SubscriptionBaseEvent cur : events) {
if (cur instanceof PhaseEvent) {
assertEquals(foundPhase, false);
foundPhase = true;
assertEquals(cur.getEffectiveDate(), expPhaseChange);
} else if (cur instanceof ApiEvent) {
final ApiEvent uEvent = (ApiEvent) cur;
assertEquals(ApiEventType.CHANGE, uEvent.getApiEventType());
assertEquals(foundChange, false);
foundChange = true;
} else {
assertFalse(true);
}
}
}
}
Aggregations