Search in sources :

Example 26 with SubscriptionBaseEvent

use of org.killbill.billing.subscription.events.SubscriptionBaseEvent in project killbill by killbill.

the class DefaultSubscriptionDao method getSubscriptionsForAccount.

@Override
public Map<UUID, List<DefaultSubscriptionBase>> getSubscriptionsForAccount(final SubscriptionCatalog catalog, @Nullable final LocalDate cutoffDt, final InternalTenantContext context) throws CatalogApiException {
    final Map<UUID, List<DefaultSubscriptionBase>> subscriptionsFromAccountId = getSubscriptionsFromAccountId(cutoffDt, context);
    final List<SubscriptionBaseEvent> eventsForAccount = getEventsForAccountId(cutoffDt, context);
    final Map<UUID, List<DefaultSubscriptionBase>> result = new HashMap<UUID, List<DefaultSubscriptionBase>>();
    final Multimap<UUID, SubscriptionBaseEvent> eventsForSubscriptions = ArrayListMultimap.create();
    for (final SubscriptionBaseEvent evt : eventsForAccount) {
        eventsForSubscriptions.put(evt.getSubscriptionId(), evt);
    }
    for (final UUID bundleId : subscriptionsFromAccountId.keySet()) {
        final List<DefaultSubscriptionBase> subscriptionsForBundle = subscriptionsFromAccountId.get(bundleId);
        result.put(bundleId, buildBundleSubscriptions(subscriptionsForBundle, eventsForSubscriptions, null, catalog, context));
    }
    return result;
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) LinkedList(java.util.LinkedList) DefaultSubscriptionBase(org.killbill.billing.subscription.api.user.DefaultSubscriptionBase) UUID(java.util.UUID) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent)

Example 27 with SubscriptionBaseEvent

use of org.killbill.billing.subscription.events.SubscriptionBaseEvent 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;
        }
    });
}
Also used : ArrayList(java.util.ArrayList) SubscriptionEventModelDao(org.killbill.billing.subscription.engine.dao.model.SubscriptionEventModelDao) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) SubscriptionApiException(org.killbill.billing.entitlement.api.SubscriptionApiException) IOException(java.io.IOException) SubscriptionBaseApiException(org.killbill.billing.subscription.api.user.SubscriptionBaseApiException) EventBusException(org.killbill.bus.api.PersistentBus.EventBusException) EntityPersistenceException(org.killbill.billing.entity.EntityPersistenceException) Predicate(com.google.common.base.Predicate) ApiEventBuilder(org.killbill.billing.subscription.events.user.ApiEventBuilder) EntitySqlDaoWrapperFactory(org.killbill.billing.util.entity.dao.EntitySqlDaoWrapperFactory) ArrayList(java.util.ArrayList) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) LinkedList(java.util.LinkedList) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent) ApiEventChange(org.killbill.billing.subscription.events.user.ApiEventChange)

Example 28 with SubscriptionBaseEvent

use of org.killbill.billing.subscription.events.SubscriptionBaseEvent 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
}
Also used : ApiEventCreate(org.killbill.billing.subscription.events.user.ApiEventCreate) ApiEventCancel(org.killbill.billing.subscription.events.user.ApiEventCancel) DateTime(org.joda.time.DateTime) LinkedList(java.util.LinkedList) PhaseEventData(org.killbill.billing.subscription.events.phase.PhaseEventData) ApiEventBuilder(org.killbill.billing.subscription.events.user.ApiEventBuilder) UUID(java.util.UUID) PhaseEventBuilder(org.killbill.billing.subscription.events.phase.PhaseEventBuilder) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent) Test(org.testng.annotations.Test)

Example 29 with SubscriptionBaseEvent

use of org.killbill.billing.subscription.events.SubscriptionBaseEvent 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
}
Also used : ApiEventCreate(org.killbill.billing.subscription.events.user.ApiEventCreate) DateTime(org.joda.time.DateTime) LinkedList(java.util.LinkedList) PhaseEventData(org.killbill.billing.subscription.events.phase.PhaseEventData) ApiEventBuilder(org.killbill.billing.subscription.events.user.ApiEventBuilder) UUID(java.util.UUID) PhaseEventBuilder(org.killbill.billing.subscription.events.phase.PhaseEventBuilder) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent) ApiEventChange(org.killbill.billing.subscription.events.user.ApiEventChange) Test(org.testng.annotations.Test)

Example 30 with SubscriptionBaseEvent

use of org.killbill.billing.subscription.events.SubscriptionBaseEvent 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
}
Also used : ApiEventCreate(org.killbill.billing.subscription.events.user.ApiEventCreate) ApiEventCancel(org.killbill.billing.subscription.events.user.ApiEventCancel) DateTime(org.joda.time.DateTime) LinkedList(java.util.LinkedList) PhaseEventData(org.killbill.billing.subscription.events.phase.PhaseEventData) ApiEventBuilder(org.killbill.billing.subscription.events.user.ApiEventBuilder) UUID(java.util.UUID) PhaseEventBuilder(org.killbill.billing.subscription.events.phase.PhaseEventBuilder) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent) Test(org.testng.annotations.Test)

Aggregations

SubscriptionBaseEvent (org.killbill.billing.subscription.events.SubscriptionBaseEvent)75 DateTime (org.joda.time.DateTime)31 ApiEventBuilder (org.killbill.billing.subscription.events.user.ApiEventBuilder)26 LinkedList (java.util.LinkedList)25 ArrayList (java.util.ArrayList)23 UUID (java.util.UUID)22 DefaultSubscriptionBase (org.killbill.billing.subscription.api.user.DefaultSubscriptionBase)21 InternalCallContext (org.killbill.billing.callcontext.InternalCallContext)16 CatalogApiException (org.killbill.billing.catalog.api.CatalogApiException)14 Test (org.testng.annotations.Test)14 Plan (org.killbill.billing.catalog.api.Plan)13 PhaseEvent (org.killbill.billing.subscription.events.phase.PhaseEvent)13 ApiEvent (org.killbill.billing.subscription.events.user.ApiEvent)13 ApiEventCancel (org.killbill.billing.subscription.events.user.ApiEventCancel)12 ApiEventCreate (org.killbill.billing.subscription.events.user.ApiEventCreate)11 SubscriptionBase (org.killbill.billing.subscription.api.SubscriptionBase)10 SubscriptionBuilder (org.killbill.billing.subscription.api.user.SubscriptionBuilder)9 SubscriptionNotificationKey (org.killbill.billing.subscription.engine.core.SubscriptionNotificationKey)8 ApiEventChange (org.killbill.billing.subscription.events.user.ApiEventChange)8 ImmutableList (com.google.common.collect.ImmutableList)7