use of org.killbill.billing.subscription.events.user.ApiEventBuilder in project killbill by killbill.
the class DefaultSubscriptionDao method mergeDryRunEvents.
private void mergeDryRunEvents(final UUID subscriptionId, final List<SubscriptionBaseEvent> events, @Nullable final Collection<SubscriptionBaseEvent> dryRunEvents) {
if (dryRunEvents == null || dryRunEvents.isEmpty()) {
return;
}
for (final SubscriptionBaseEvent curDryRun : dryRunEvents) {
boolean swapChangeEventWithCreate = false;
if (curDryRun.getSubscriptionId() != null && curDryRun.getSubscriptionId().equals(subscriptionId)) {
final boolean isApiChange = curDryRun.getType() == EventType.API_USER && ((ApiEvent) curDryRun).getApiEventType() == ApiEventType.CHANGE;
final Iterator<SubscriptionBaseEvent> it = events.iterator();
while (it.hasNext()) {
final SubscriptionBaseEvent event = it.next();
if (event.getEffectiveDate().isAfter(curDryRun.getEffectiveDate())) {
it.remove();
} else if (event.getEffectiveDate().compareTo(curDryRun.getEffectiveDate()) == 0 && isApiChange && (event.getType() == EventType.API_USER && (((ApiEvent) event).getApiEventType() == ApiEventType.CREATE) || ((ApiEvent) event).getApiEventType() == ApiEventType.TRANSFER)) {
it.remove();
swapChangeEventWithCreate = true;
}
}
// Set total ordering value of the fake dryRun event to make sure billing events are correctly ordered
// and also transform CHANGE event into CREATE in case of perfect effectiveDate match
final EventBaseBuilder eventBuilder;
switch(curDryRun.getType()) {
case PHASE:
eventBuilder = new PhaseEventBuilder((PhaseEvent) curDryRun);
break;
case BCD_UPDATE:
eventBuilder = new BCDEventBuilder((BCDEvent) curDryRun);
break;
case API_USER:
default:
eventBuilder = new ApiEventBuilder((ApiEvent) curDryRun);
if (swapChangeEventWithCreate) {
((ApiEventBuilder) eventBuilder).setApiEventType(ApiEventType.CREATE);
}
break;
}
if (!events.isEmpty()) {
eventBuilder.setTotalOrdering(events.get(events.size() - 1).getTotalOrdering() + 1);
}
events.add(eventBuilder.build());
}
}
}
use of org.killbill.billing.subscription.events.user.ApiEventBuilder in project killbill by killbill.
the class DefaultSubscriptionDao method changePlan.
@Override
public void changePlan(final DefaultSubscriptionBase subscription, final List<SubscriptionBaseEvent> originalInputChangeEvents, final List<DefaultSubscriptionBase> subscriptionsToBeCancelled, final List<SubscriptionBaseEvent> cancelEvents, final SubscriptionCatalog catalog, final InternalCallContext context) {
// First event is expected to be the subscription CHANGE event
final SubscriptionBaseEvent inputChangeEvent = originalInputChangeEvents.get(0);
Preconditions.checkState(inputChangeEvent.getType() == EventType.API_USER && ((ApiEvent) inputChangeEvent).getApiEventType() == ApiEventType.CHANGE);
Preconditions.checkState(inputChangeEvent.getSubscriptionId().equals(subscription.getId()));
transactionalSqlDao.execute(false, new EntitySqlDaoTransactionWrapper<Void>() {
@Override
public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
final SubscriptionEventSqlDao transactional = entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class);
final List<SubscriptionEventModelDao> activeSubscriptionEvents = entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class).getActiveEventsForSubscription(subscription.getId().toString(), context);
// First event is CREATE/TRANSFER event
final SubscriptionEventModelDao firstSubscriptionEvent = activeSubscriptionEvents.get(0);
final Iterable<SubscriptionEventModelDao> activePresentOrFutureSubscriptionEvents = Iterables.filter(activeSubscriptionEvents, new Predicate<SubscriptionEventModelDao>() {
@Override
public boolean apply(SubscriptionEventModelDao input) {
return input.getEffectiveDate().compareTo(inputChangeEvent.getEffectiveDate()) >= 0;
}
});
// We do a little magic here in case the CHANGE coincides exactly with the CREATE event to invalidate original CREATE event and
// change the input CHANGE event into a CREATE event.
final boolean isChangePlanOnStartDate = firstSubscriptionEvent.getEffectiveDate().compareTo(inputChangeEvent.getEffectiveDate()) == 0;
final List<SubscriptionBaseEvent> inputChangeEvents;
if (isChangePlanOnStartDate) {
// Rebuild input event list with first the CREATE event and all original input events except for inputChangeEvent
inputChangeEvents = new ArrayList<SubscriptionBaseEvent>();
final SubscriptionBaseEvent newCreateEvent = new ApiEventBuilder((ApiEventChange) inputChangeEvent).setApiEventType(firstSubscriptionEvent.getUserType()).build();
originalInputChangeEvents.remove(0);
inputChangeEvents.add(newCreateEvent);
inputChangeEvents.addAll(originalInputChangeEvents);
// Deactivate original CREATE event
unactivateEventFromTransaction(firstSubscriptionEvent, entitySqlDaoWrapperFactory, context);
} else {
inputChangeEvents = originalInputChangeEvents;
}
cancelFutureEventsFromTransaction(activePresentOrFutureSubscriptionEvents, entitySqlDaoWrapperFactory, false, context);
for (final SubscriptionBaseEvent cur : inputChangeEvents) {
createAndRefresh(transactional, new SubscriptionEventModelDao(cur), context);
final boolean isBusEvent = cur.getEffectiveDate().compareTo(context.getCreatedDate()) <= 0 && (cur.getType() == EventType.API_USER || cur.getType() == EventType.BCD_UPDATE);
recordBusOrFutureNotificationFromTransaction(subscription, cur, entitySqlDaoWrapperFactory, isBusEvent, 0, catalog, context);
}
// Notify the Bus of the latest requested change
final SubscriptionBaseEvent finalEvent = inputChangeEvents.get(inputChangeEvents.size() - 1);
notifyBusOfRequestedChange(entitySqlDaoWrapperFactory, subscription, finalEvent, SubscriptionBaseTransitionType.CHANGE, 0, context);
// Cancel associated add-ons
cancelSubscriptionsFromTransaction(entitySqlDaoWrapperFactory, subscriptionsToBeCancelled, cancelEvents, catalog, context);
return null;
}
});
}
use of org.killbill.billing.subscription.events.user.ApiEventBuilder in project killbill by killbill.
the class TestSubscriptionBillingEvents method testWithCancelation_After_EffSubDtV2.
@Test(groups = "fast")
public void testWithCancelation_After_EffSubDtV2() throws Exception {
final DateTime createDate = new DateTime(2011, 1, 2, 0, 0, DateTimeZone.UTC);
final DefaultSubscriptionBase subscriptionBase = new DefaultSubscriptionBase(new SubscriptionBuilder().setAlignStartDate(createDate));
final UUID subscriptionId = UUID.randomUUID();
final List<SubscriptionBaseEvent> inputEvents = new LinkedList<SubscriptionBaseEvent>();
inputEvents.add(new ApiEventCreate(new ApiEventBuilder().setApiEventType(CREATE).setEventPlan("gold-monthly").setEventPlanPhase("gold-monthly-trial").setEventPriceList("DEFAULT").setFromDisk(true).setUuid(UUID.randomUUID()).setSubscriptionId(subscriptionId).setCreatedDate(createDate).setUpdatedDate(createDate).setEffectiveDate(createDate).setTotalOrdering(1).setActive(true)));
final DateTime evergreenPhaseDate = createDate.plusDays(30);
inputEvents.add(new PhaseEventData(new PhaseEventBuilder().setPhaseName("gold-monthly-evergreen").setUuid(UUID.randomUUID()).setSubscriptionId(subscriptionId).setCreatedDate(evergreenPhaseDate).setUpdatedDate(evergreenPhaseDate).setEffectiveDate(evergreenPhaseDate).setTotalOrdering(2).setActive(true)));
final DateTime cancelDate = new DateTime(2011, 2, 15, 0, 0, DateTimeZone.UTC);
inputEvents.add(new ApiEventCancel(new ApiEventBuilder().setApiEventType(ApiEventType.CANCEL).setEventPlan(null).setEventPlanPhase(null).setEventPriceList(null).setFromDisk(true).setUuid(UUID.randomUUID()).setSubscriptionId(subscriptionId).setCreatedDate(createDate).setUpdatedDate(null).setEffectiveDate(cancelDate).setTotalOrdering(3).setActive(true)));
subscriptionBase.rebuildTransitions(inputEvents, catalog);
final List<SubscriptionBillingEvent> result = subscriptionBase.getSubscriptionBillingEvents(catalog.getCatalog());
Assert.assertEquals(result.size(), 5);
Assert.assertEquals(result.get(0).getType(), SubscriptionBaseTransitionType.CREATE);
Assert.assertEquals(result.get(0).getEffectiveDate().compareTo(createDate), 0);
Assert.assertEquals(result.get(0).getPlan().getName().compareTo("gold-monthly"), 0);
Assert.assertEquals(toDateTime(result.get(0).getPlan().getCatalog().getEffectiveDate()).compareTo(EFF_V1), 0);
Assert.assertEquals(result.get(1).getType(), SubscriptionBaseTransitionType.PHASE);
Assert.assertEquals(result.get(1).getEffectiveDate().compareTo(evergreenPhaseDate), 0);
Assert.assertEquals(result.get(1).getPlan().getName().compareTo("gold-monthly"), 0);
Assert.assertEquals(toDateTime(result.get(1).getPlan().getCatalog().getEffectiveDate()).compareTo(EFF_V1), 0);
// Catalog change event for EFF_SUB_DT_V2
Assert.assertEquals(result.get(2).getType(), SubscriptionBaseTransitionType.CHANGE);
Assert.assertEquals(result.get(2).getEffectiveDate().compareTo(EFF_SUB_DT_V2), 0);
Assert.assertEquals(result.get(2).getPlan().getName().compareTo("gold-monthly"), 0);
Assert.assertEquals(toDateTime(result.get(2).getPlan().getCatalog().getEffectiveDate()).compareTo(EFF_V2), 0);
// Catalog change event for EFF_SUB_DT_V3
Assert.assertEquals(result.get(3).getType(), SubscriptionBaseTransitionType.CHANGE);
Assert.assertEquals(result.get(3).getEffectiveDate().compareTo(EFF_SUB_DT_V3), 0);
Assert.assertEquals(result.get(3).getPlan().getName().compareTo("gold-monthly"), 0);
Assert.assertEquals(toDateTime(result.get(3).getPlan().getCatalog().getEffectiveDate()).compareTo(EFF_V3), 0);
// Cancel event
Assert.assertEquals(result.get(4).getType(), SubscriptionBaseTransitionType.CANCEL);
Assert.assertEquals(result.get(4).getEffectiveDate().compareTo(cancelDate), 0);
Assert.assertNull(result.get(4).getPlan());
// Nothing after cancel -> we correctly discarded subsequent catalog update events after the cancel
}
use of org.killbill.billing.subscription.events.user.ApiEventBuilder in project killbill by killbill.
the class TestSubscriptionBillingEvents method testWithChange_Before_EffSubDtV2.
@Test(groups = "fast")
public void testWithChange_Before_EffSubDtV2() throws Exception {
final DateTime createDate = new DateTime(2011, 1, 2, 0, 0, DateTimeZone.UTC);
final DefaultSubscriptionBase subscriptionBase = new DefaultSubscriptionBase(new SubscriptionBuilder().setAlignStartDate(createDate));
final UUID subscriptionId = UUID.randomUUID();
final List<SubscriptionBaseEvent> inputEvents = new LinkedList<SubscriptionBaseEvent>();
inputEvents.add(new ApiEventCreate(new ApiEventBuilder().setApiEventType(CREATE).setEventPlan("gold-monthly").setEventPlanPhase("gold-monthly-trial").setEventPriceList("DEFAULT").setFromDisk(true).setUuid(UUID.randomUUID()).setSubscriptionId(subscriptionId).setCreatedDate(createDate).setUpdatedDate(createDate).setEffectiveDate(createDate).setTotalOrdering(1).setActive(true)));
final DateTime evergreenPhaseDate = createDate.plusDays(30);
inputEvents.add(new PhaseEventData(new PhaseEventBuilder().setPhaseName("gold-monthly-evergreen").setUuid(UUID.randomUUID()).setSubscriptionId(subscriptionId).setCreatedDate(evergreenPhaseDate).setUpdatedDate(evergreenPhaseDate).setEffectiveDate(evergreenPhaseDate).setTotalOrdering(2).setActive(true)));
final DateTime changeDate = new DateTime(2011, 2, 13, 0, 0, DateTimeZone.UTC);
inputEvents.add(new ApiEventChange(new ApiEventBuilder().setApiEventType(ApiEventType.CHANGE).setEventPlan("silver-monthly").setEventPlanPhase("silver-monthly-evergreen").setEventPriceList("DEFAULT").setFromDisk(true).setUuid(UUID.randomUUID()).setSubscriptionId(subscriptionId).setCreatedDate(changeDate).setUpdatedDate(null).setEffectiveDate(changeDate).setTotalOrdering(3).setActive(true)));
subscriptionBase.rebuildTransitions(inputEvents, catalog);
final List<SubscriptionBillingEvent> result = subscriptionBase.getSubscriptionBillingEvents(catalog.getCatalog());
Assert.assertEquals(result.size(), 3);
Assert.assertEquals(result.get(0).getType(), SubscriptionBaseTransitionType.CREATE);
Assert.assertEquals(result.get(0).getEffectiveDate().compareTo(createDate), 0);
Assert.assertEquals(result.get(0).getPlan().getName().compareTo("gold-monthly"), 0);
Assert.assertEquals(toDateTime(result.get(0).getPlan().getCatalog().getEffectiveDate()).compareTo(EFF_V1), 0);
Assert.assertEquals(result.get(1).getType(), SubscriptionBaseTransitionType.PHASE);
Assert.assertEquals(result.get(1).getEffectiveDate().compareTo(evergreenPhaseDate), 0);
Assert.assertEquals(result.get(1).getPlan().getName().compareTo("gold-monthly"), 0);
Assert.assertEquals(toDateTime(result.get(1).getPlan().getCatalog().getEffectiveDate()).compareTo(EFF_V1), 0);
// User CHANGE event
Assert.assertEquals(result.get(2).getType(), SubscriptionBaseTransitionType.CHANGE);
Assert.assertEquals(result.get(2).getEffectiveDate().compareTo(changeDate), 0);
Assert.assertEquals(result.get(2).getPlan().getName().compareTo("silver-monthly"), 0);
Assert.assertEquals(toDateTime(result.get(2).getPlan().getCatalog().getEffectiveDate()).compareTo(EFF_V3), 0);
// We should not see any catalog CHANGE events
}
use of org.killbill.billing.subscription.events.user.ApiEventBuilder in project killbill by killbill.
the class TestSubscriptionBillingEvents method testWithCancelation_Before_EffSubDtV2.
@Test(groups = "fast")
public void testWithCancelation_Before_EffSubDtV2() throws Exception {
final DateTime createDate = new DateTime(2011, 1, 2, 0, 0, DateTimeZone.UTC);
final DefaultSubscriptionBase subscriptionBase = new DefaultSubscriptionBase(new SubscriptionBuilder().setAlignStartDate(createDate));
final UUID subscriptionId = UUID.randomUUID();
final List<SubscriptionBaseEvent> inputEvents = new LinkedList<SubscriptionBaseEvent>();
inputEvents.add(new ApiEventCreate(new ApiEventBuilder().setApiEventType(CREATE).setEventPlan("gold-monthly").setEventPlanPhase("gold-monthly-trial").setEventPriceList("DEFAULT").setFromDisk(true).setUuid(UUID.randomUUID()).setSubscriptionId(subscriptionId).setCreatedDate(createDate).setUpdatedDate(createDate).setEffectiveDate(createDate).setTotalOrdering(1).setActive(true)));
final DateTime evergreenPhaseDate = createDate.plusDays(30);
inputEvents.add(new PhaseEventData(new PhaseEventBuilder().setPhaseName("gold-monthly-evergreen").setUuid(UUID.randomUUID()).setSubscriptionId(subscriptionId).setCreatedDate(evergreenPhaseDate).setUpdatedDate(evergreenPhaseDate).setEffectiveDate(evergreenPhaseDate).setTotalOrdering(1).setActive(true)));
final DateTime cancelDate = new DateTime(2011, 2, 13, 0, 0, DateTimeZone.UTC);
inputEvents.add(new ApiEventCancel(new ApiEventBuilder().setApiEventType(ApiEventType.CANCEL).setEventPlan(null).setEventPlanPhase(null).setEventPriceList(null).setFromDisk(true).setUuid(UUID.randomUUID()).setSubscriptionId(subscriptionId).setCreatedDate(createDate).setUpdatedDate(null).setEffectiveDate(cancelDate).setTotalOrdering(2).setActive(true)));
subscriptionBase.rebuildTransitions(inputEvents, catalog);
final List<SubscriptionBillingEvent> result = subscriptionBase.getSubscriptionBillingEvents(catalog.getCatalog());
Assert.assertEquals(result.size(), 3);
Assert.assertEquals(result.get(0).getType(), SubscriptionBaseTransitionType.CREATE);
Assert.assertEquals(result.get(0).getEffectiveDate().compareTo(createDate), 0);
Assert.assertEquals(result.get(0).getPlan().getName().compareTo("gold-monthly"), 0);
Assert.assertEquals(toDateTime(result.get(0).getPlan().getCatalog().getEffectiveDate()).compareTo(EFF_V1), 0);
Assert.assertEquals(result.get(1).getType(), SubscriptionBaseTransitionType.PHASE);
Assert.assertEquals(result.get(1).getEffectiveDate().compareTo(evergreenPhaseDate), 0);
Assert.assertEquals(result.get(1).getPlan().getName().compareTo("gold-monthly"), 0);
Assert.assertEquals(toDateTime(result.get(1).getPlan().getCatalog().getEffectiveDate()).compareTo(EFF_V1), 0);
// Cancel event
Assert.assertEquals(result.get(2).getType(), SubscriptionBaseTransitionType.CANCEL);
Assert.assertEquals(result.get(2).getEffectiveDate().compareTo(cancelDate), 0);
Assert.assertNull(result.get(2).getPlan());
// Nothing after cancel -> we correctly discarded subsequent catalog update events after the cancel
}
Aggregations