Search in sources :

Example 6 with SubscriptionBaseTransition

use of org.killbill.billing.subscription.api.user.SubscriptionBaseTransition in project killbill by killbill.

the class TestDefaultSubscriptionBundleTimeline method testVariousBlockingStatesAtTheSameEffectiveDateImpl.

private void testVariousBlockingStatesAtTheSameEffectiveDateImpl(final boolean regressionFlagForOlderVersionThan_0_17_X) throws CatalogApiException {
    clock.setDay(new LocalDate(2013, 1, 1));
    final DateTimeZone accountTimeZone = DateTimeZone.UTC;
    final UUID accountId = UUID.randomUUID();
    final UUID bundleId = UUID.randomUUID();
    final String externalKey = "foo";
    final UUID entitlementId = UUID.randomUUID();
    final List<SubscriptionBaseTransition> allTransitions = new ArrayList<SubscriptionBaseTransition>();
    final List<BlockingState> blockingStates = new ArrayList<BlockingState>();
    DateTime effectiveDate = new DateTime(2013, 1, 1, 15, 43, 25, 0, DateTimeZone.UTC);
    final SubscriptionBaseTransition tr1 = createTransition(entitlementId, EventType.API_USER, ApiEventType.CREATE, effectiveDate, clock.getUTCNow(), null, "trial");
    allTransitions.add(tr1);
    if (!regressionFlagForOlderVersionThan_0_17_X) {
        final BlockingState bsCreate = new DefaultBlockingState(UUID.randomUUID(), entitlementId, BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_START, DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME, false, false, false, effectiveDate, clock.getUTCNow(), clock.getUTCNow(), 0L);
        blockingStates.add(bsCreate);
    }
    // 2013-02-10
    effectiveDate = effectiveDate.plusDays(40);
    clock.addDays(40);
    final BlockingState bs1 = new DefaultBlockingState(UUID.randomUUID(), bundleId, BlockingStateType.SUBSCRIPTION_BUNDLE, DefaultEntitlementApi.ENT_STATE_BLOCKED, DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, true, effectiveDate, clock.getUTCNow(), clock.getUTCNow(), 0L);
    blockingStates.add(bs1);
    // Same timestamp on purpose
    final BlockingState bs2 = new DefaultBlockingState(UUID.randomUUID(), bundleId, BlockingStateType.SUBSCRIPTION_BUNDLE, DefaultEntitlementApi.ENT_STATE_CLEAR, DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME, false, false, false, effectiveDate, clock.getUTCNow(), clock.getUTCNow(), 1L);
    blockingStates.add(bs2);
    // 2013-02-20
    effectiveDate = effectiveDate.plusDays(10);
    clock.addDays(10);
    final BlockingState bs3 = new DefaultBlockingState(UUID.randomUUID(), bundleId, BlockingStateType.SUBSCRIPTION_BUNDLE, DefaultEntitlementApi.ENT_STATE_BLOCKED, DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, true, effectiveDate, clock.getUTCNow(), clock.getUTCNow(), 2L);
    blockingStates.add(bs3);
    // 2013-03-02
    effectiveDate = effectiveDate.plusDays(10);
    clock.addDays(10);
    final BlockingState bs4 = new DefaultBlockingState(UUID.randomUUID(), bundleId, BlockingStateType.SUBSCRIPTION_BUNDLE, DefaultEntitlementApi.ENT_STATE_CLEAR, DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME, false, false, false, effectiveDate, clock.getUTCNow(), clock.getUTCNow(), 3L);
    blockingStates.add(bs4);
    final String overdueService = "overdue-service";
    // 2013-03-04
    effectiveDate = effectiveDate.plusDays(2);
    clock.addDays(2);
    final BlockingState bs5 = new DefaultBlockingState(UUID.randomUUID(), accountId, BlockingStateType.ACCOUNT, "OD1", overdueService, false, false, false, effectiveDate, clock.getUTCNow(), clock.getUTCNow(), 4L);
    blockingStates.add(bs5);
    final List<Entitlement> entitlements = new ArrayList<Entitlement>();
    final Entitlement entitlement = createEntitlement(entitlementId, allTransitions, blockingStates);
    entitlements.add(entitlement);
    final SubscriptionBundleTimeline timeline = new DefaultSubscriptionBundleTimeline(accountId, bundleId, externalKey, entitlements, internalCallContext);
    final List<SubscriptionEvent> events = timeline.getSubscriptionEvents();
    assertEquals(events.size(), 11);
    assertEquals(events.get(0).getEffectiveDate().compareTo(new LocalDate(tr1.getEffectiveTransitionTime(), accountTimeZone)), 0);
    assertEquals(events.get(1).getEffectiveDate().compareTo(new LocalDate(tr1.getEffectiveTransitionTime(), accountTimeZone)), 0);
    assertEquals(events.get(2).getEffectiveDate().compareTo(new LocalDate(bs1.getEffectiveDate(), accountTimeZone)), 0);
    assertEquals(events.get(3).getEffectiveDate().compareTo(new LocalDate(bs1.getEffectiveDate(), accountTimeZone)), 0);
    assertEquals(events.get(4).getEffectiveDate().compareTo(new LocalDate(bs2.getEffectiveDate(), accountTimeZone)), 0);
    assertEquals(events.get(5).getEffectiveDate().compareTo(new LocalDate(bs2.getEffectiveDate(), accountTimeZone)), 0);
    assertEquals(events.get(6).getEffectiveDate().compareTo(new LocalDate(bs3.getEffectiveDate(), accountTimeZone)), 0);
    assertEquals(events.get(7).getEffectiveDate().compareTo(new LocalDate(bs3.getEffectiveDate(), accountTimeZone)), 0);
    assertEquals(events.get(8).getEffectiveDate().compareTo(new LocalDate(bs4.getEffectiveDate(), accountTimeZone)), 0);
    assertEquals(events.get(9).getEffectiveDate().compareTo(new LocalDate(bs4.getEffectiveDate(), accountTimeZone)), 0);
    assertEquals(events.get(10).getEffectiveDate().compareTo(new LocalDate(bs5.getEffectiveDate(), accountTimeZone)), 0);
    assertEquals(events.get(0).getSubscriptionEventType(), SubscriptionEventType.START_ENTITLEMENT);
    assertEquals(events.get(1).getSubscriptionEventType(), SubscriptionEventType.START_BILLING);
    assertEquals(events.get(2).getSubscriptionEventType(), SubscriptionEventType.PAUSE_ENTITLEMENT);
    assertEquals(events.get(3).getSubscriptionEventType(), SubscriptionEventType.PAUSE_BILLING);
    assertEquals(events.get(4).getSubscriptionEventType(), SubscriptionEventType.RESUME_ENTITLEMENT);
    assertEquals(events.get(5).getSubscriptionEventType(), SubscriptionEventType.RESUME_BILLING);
    assertEquals(events.get(6).getSubscriptionEventType(), SubscriptionEventType.PAUSE_ENTITLEMENT);
    assertEquals(events.get(7).getSubscriptionEventType(), SubscriptionEventType.PAUSE_BILLING);
    assertEquals(events.get(8).getSubscriptionEventType(), SubscriptionEventType.RESUME_ENTITLEMENT);
    assertEquals(events.get(9).getSubscriptionEventType(), SubscriptionEventType.RESUME_BILLING);
    assertEquals(events.get(10).getSubscriptionEventType(), SubscriptionEventType.SERVICE_STATE_CHANGE);
    assertEquals(events.get(0).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
    assertEquals(events.get(1).getServiceName(), EntitlementOrderingBase.BILLING_SERVICE_NAME);
    assertEquals(events.get(2).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
    assertEquals(events.get(3).getServiceName(), EntitlementOrderingBase.BILLING_SERVICE_NAME);
    assertEquals(events.get(4).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
    assertEquals(events.get(5).getServiceName(), EntitlementOrderingBase.BILLING_SERVICE_NAME);
    assertEquals(events.get(6).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
    assertEquals(events.get(7).getServiceName(), EntitlementOrderingBase.BILLING_SERVICE_NAME);
    assertEquals(events.get(8).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
    assertEquals(events.get(9).getServiceName(), EntitlementOrderingBase.BILLING_SERVICE_NAME);
    assertEquals(events.get(10).getServiceName(), overdueService);
    assertNull(events.get(0).getPrevPhase());
    assertNull(events.get(1).getPrevPhase());
    assertEquals(events.get(1).getNextPhase().getName(), "trial");
    assertEquals(events.get(2).getPrevPhase().getName(), "trial");
    assertEquals(events.get(2).getNextPhase().getName(), "trial");
    assertEquals(events.get(3).getPrevPhase().getName(), "trial");
    assertEquals(events.get(3).getNextPhase().getName(), "trial");
    assertEquals(events.get(4).getPrevPhase().getName(), "trial");
    assertEquals(events.get(4).getNextPhase().getName(), "trial");
    assertEquals(events.get(5).getPrevPhase().getName(), "trial");
    assertEquals(events.get(5).getNextPhase().getName(), "trial");
    assertEquals(events.get(6).getPrevPhase().getName(), "trial");
    assertEquals(events.get(6).getNextPhase().getName(), "trial");
    assertEquals(events.get(7).getPrevPhase().getName(), "trial");
    assertEquals(events.get(7).getNextPhase().getName(), "trial");
    assertEquals(events.get(8).getPrevPhase().getName(), "trial");
    assertEquals(events.get(8).getNextPhase().getName(), "trial");
    assertEquals(events.get(9).getPrevPhase().getName(), "trial");
    assertEquals(events.get(9).getNextPhase().getName(), "trial");
    assertEquals(events.get(10).getPrevPhase().getName(), "trial");
    assertEquals(events.get(10).getNextPhase().getName(), "trial");
}
Also used : ArrayList(java.util.ArrayList) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) LocalDate(org.joda.time.LocalDate) DateTimeZone(org.joda.time.DateTimeZone) DateTime(org.joda.time.DateTime) UUID(java.util.UUID) SubscriptionBaseTransition(org.killbill.billing.subscription.api.user.SubscriptionBaseTransition) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState)

Example 7 with SubscriptionBaseTransition

use of org.killbill.billing.subscription.api.user.SubscriptionBaseTransition in project killbill by killbill.

the class TestBillingAlignment method testTransitionAccountBAToSubscriptionBA.

@Test(groups = "slow")
public void testTransitionAccountBAToSubscriptionBA() throws Exception {
    // We take april as it has 30 days (easier to play with BCD)
    // Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
    clock.setDay(new LocalDate(2012, 4, 1));
    // Set the BCD to the 25th
    final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(25));
    //
    // CREATE SUBSCRIPTION AND EXPECT BOTH EVENTS: NextEvent.CREATE NextEvent.INVOICE
    // (Start with monthly that has an 'Account' billing alignment)
    //
    final DefaultEntitlement bpEntitlement = createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey", "Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
    assertNotNull(bpEntitlement);
    invoiceChecker.checkInvoice(account.getId(), 1, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2012, 4, 1), null, InvoiceItemType.FIXED, new BigDecimal("0")));
    invoiceChecker.checkChargedThroughDate(bpEntitlement.getId(), new LocalDate(2012, 4, 1), callContext);
    // GET OUT TRIAL (moving clock to 2012-05-04)
    addDaysAndCheckForCompletion(33, NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
    invoiceChecker.checkInvoice(account.getId(), 2, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 1), new LocalDate(2012, 5, 25), InvoiceItemType.RECURRING, new BigDecimal("199.96")));
    invoiceChecker.checkChargedThroughDate(bpEntitlement.getId(), new LocalDate(2012, 5, 25), callContext);
    // Change plan to annual that has been configured to have a 'Subscription' billing alignment
    final DefaultEntitlement changedBpEntitlement = changeEntitlementAndCheckForCompletion(bpEntitlement, "Shotgun", BillingPeriod.ANNUAL, null, NextEvent.CHANGE, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
    invoiceChecker.checkInvoice(account.getId(), 3, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 4), new LocalDate(2013, 5, 1), InvoiceItemType.RECURRING, new BigDecimal("2380.22")), new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 4), new LocalDate(2012, 5, 25), InvoiceItemType.REPAIR_ADJ, new BigDecimal("-174.97")));
    invoiceChecker.checkChargedThroughDate(bpEntitlement.getId(), new LocalDate(2013, 5, 1), callContext);
    Assert.assertEquals(changedBpEntitlement.getSubscriptionBase().getAllTransitions().size(), 3);
    final SubscriptionBaseTransition trial = changedBpEntitlement.getSubscriptionBase().getAllTransitions().get(0);
    Assert.assertEquals(trial.getEffectiveTransitionTime().toLocalDate().compareTo(new LocalDate(2012, 4, 1)), 0);
    Assert.assertEquals(trial.getNextPhase().getName(), "shotgun-monthly-trial");
    final SubscriptionBaseTransition smEvergreen = changedBpEntitlement.getSubscriptionBase().getAllTransitions().get(1);
    Assert.assertEquals(smEvergreen.getEffectiveTransitionTime().toLocalDate().compareTo(new LocalDate(2012, 5, 1)), 0);
    Assert.assertEquals(smEvergreen.getNextPhase().getName(), "shotgun-monthly-evergreen");
    final SubscriptionBaseTransition saEvergreen = changedBpEntitlement.getSubscriptionBase().getAllTransitions().get(2);
    // Verify the IMMEDIATE policy
    Assert.assertEquals(saEvergreen.getEffectiveTransitionTime().toLocalDate().compareTo(new LocalDate(2012, 5, 4)), 0);
    // Verify the START_OF_SUBSCRIPTION alignment (both plans have the same 30 days trial)
    Assert.assertEquals(saEvergreen.getNextPhase().getName(), "shotgun-annual-evergreen");
}
Also used : Account(org.killbill.billing.account.api.Account) DefaultEntitlement(org.killbill.billing.entitlement.api.DefaultEntitlement) SubscriptionBaseTransition(org.killbill.billing.subscription.api.user.SubscriptionBaseTransition) LocalDate(org.joda.time.LocalDate) ExpectedInvoiceItemCheck(org.killbill.billing.beatrix.util.InvoiceChecker.ExpectedInvoiceItemCheck) BigDecimal(java.math.BigDecimal) Test(org.testng.annotations.Test)

Example 8 with SubscriptionBaseTransition

use of org.killbill.billing.subscription.api.user.SubscriptionBaseTransition in project killbill by killbill.

the class SubscriptionChecker method checkSubscriptionCreated.

public SubscriptionBase checkSubscriptionCreated(final UUID subscriptionId, final InternalCallContext context) throws SubscriptionBaseApiException {
    final UUID tenantId = nonEntityDao.retrieveIdFromObject(context.getTenantRecordId(), ObjectType.TENANT, cacheControllerDispatcher.getCacheController(CacheType.OBJECT_ID));
    final CallContext callContext = context.toCallContext(tenantId);
    final SubscriptionBase subscription = subscriptionApi.getSubscriptionFromId(subscriptionId, context);
    Assert.assertNotNull(subscription);
    auditChecker.checkSubscriptionCreated(subscription.getBundleId(), subscriptionId, callContext);
    List<SubscriptionBaseTransition> subscriptionEvents = getSubscriptionEvents(subscription);
    Assert.assertTrue(subscriptionEvents.size() >= 1);
    auditChecker.checkSubscriptionEventCreated(subscription.getBundleId(), ((SubscriptionBaseTransitionData) subscriptionEvents.get(0)).getId(), callContext);
    auditChecker.checkBundleCreated(subscription.getBundleId(), callContext);
    return subscription;
}
Also used : SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) UUID(java.util.UUID) SubscriptionBaseTransition(org.killbill.billing.subscription.api.user.SubscriptionBaseTransition) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) CallContext(org.killbill.billing.util.callcontext.CallContext)

Example 9 with SubscriptionBaseTransition

use of org.killbill.billing.subscription.api.user.SubscriptionBaseTransition in project killbill by killbill.

the class DefaultEventsStream method computeAddonsBlockingStatesForNextSubscriptionBaseEvent.

private Collection<BlockingState> computeAddonsBlockingStatesForNextSubscriptionBaseEvent(final DateTime effectiveDate, final boolean useBillingEffectiveDate) {
    SubscriptionBaseTransition subscriptionBaseTransitionTrigger = null;
    if (!isEntitlementFutureCancelled()) {
        // Compute the transition trigger (either subscription cancel or change)
        final Iterable<SubscriptionBaseTransition> pendingSubscriptionBaseTransitions = getPendingSubscriptionEvents(effectiveDate, SubscriptionBaseTransitionType.CHANGE, SubscriptionBaseTransitionType.CANCEL);
        if (!pendingSubscriptionBaseTransitions.iterator().hasNext()) {
            return ImmutableList.<BlockingState>of();
        }
        subscriptionBaseTransitionTrigger = pendingSubscriptionBaseTransitions.iterator().next();
    }
    final Product baseTransitionTriggerNextProduct;
    final DateTime blockingStateEffectiveDate;
    if (subscriptionBaseTransitionTrigger == null) {
        baseTransitionTriggerNextProduct = null;
        blockingStateEffectiveDate = effectiveDate;
    } else {
        baseTransitionTriggerNextProduct = (EntitlementState.CANCELLED.equals(subscriptionBaseTransitionTrigger.getNextState()) ? null : subscriptionBaseTransitionTrigger.getNextPlan().getProduct());
        blockingStateEffectiveDate = useBillingEffectiveDate ? subscriptionBaseTransitionTrigger.getEffectiveTransitionTime() : effectiveDate;
    }
    return computeAddonsBlockingStatesForSubscriptionBaseEvent(baseTransitionTriggerNextProduct, blockingStateEffectiveDate);
}
Also used : Product(org.killbill.billing.catalog.api.Product) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) BlockingState(org.killbill.billing.entitlement.api.BlockingState) SubscriptionBaseTransition(org.killbill.billing.subscription.api.user.SubscriptionBaseTransition) DateTime(org.joda.time.DateTime)

Example 10 with SubscriptionBaseTransition

use of org.killbill.billing.subscription.api.user.SubscriptionBaseTransition in project killbill by killbill.

the class EventsStreamBuilder method createPlanPhaseSpecifier.

private PlanPhaseSpecifier createPlanPhaseSpecifier(final SubscriptionBase subscription) {
    final String lastActiveProductName;
    final BillingPeriod billingPeriod;
    final ProductCategory productCategory;
    final String priceListName;
    final PhaseType phaseType;
    if (subscription.getState() == EntitlementState.PENDING) {
        final SubscriptionBaseTransition transition = subscription.getPendingTransition();
        final Product pendingProduct = transition.getNextPlan().getProduct();
        lastActiveProductName = pendingProduct.getName();
        productCategory = pendingProduct.getCategory();
        final PlanPhase pendingPlanPhase = transition.getNextPhase();
        billingPeriod = pendingPlanPhase.getRecurring() != null ? pendingPlanPhase.getRecurring().getBillingPeriod() : BillingPeriod.NO_BILLING_PERIOD;
        priceListName = transition.getNextPriceList().getName();
        phaseType = transition.getNextPhase().getPhaseType();
    } else {
        final Product lastActiveProduct = subscription.getLastActiveProduct();
        lastActiveProductName = lastActiveProduct.getName();
        productCategory = lastActiveProduct.getCategory();
        final PlanPhase lastActivePlanPhase = subscription.getLastActivePhase();
        billingPeriod = lastActivePlanPhase.getRecurring() != null ? lastActivePlanPhase.getRecurring().getBillingPeriod() : BillingPeriod.NO_BILLING_PERIOD;
        priceListName = subscription.getLastActivePlan().getPriceListName();
        phaseType = subscription.getLastActivePhase().getPhaseType();
    }
    return new PlanPhaseSpecifier(lastActiveProductName, billingPeriod, priceListName, phaseType);
}
Also used : PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) BillingPeriod(org.killbill.billing.catalog.api.BillingPeriod) ProductCategory(org.killbill.billing.catalog.api.ProductCategory) PhaseType(org.killbill.billing.catalog.api.PhaseType) Product(org.killbill.billing.catalog.api.Product) PlanPhase(org.killbill.billing.catalog.api.PlanPhase) SubscriptionBaseTransition(org.killbill.billing.subscription.api.user.SubscriptionBaseTransition)

Aggregations

SubscriptionBaseTransition (org.killbill.billing.subscription.api.user.SubscriptionBaseTransition)17 ArrayList (java.util.ArrayList)12 UUID (java.util.UUID)12 DateTime (org.joda.time.DateTime)12 LocalDate (org.joda.time.LocalDate)12 DefaultBlockingState (org.killbill.billing.junction.DefaultBlockingState)12 DateTimeZone (org.joda.time.DateTimeZone)10 Product (org.killbill.billing.catalog.api.Product)2 SubscriptionBase (org.killbill.billing.subscription.api.SubscriptionBase)2 BigDecimal (java.math.BigDecimal)1 LinkedList (java.util.LinkedList)1 Account (org.killbill.billing.account.api.Account)1 ExpectedInvoiceItemCheck (org.killbill.billing.beatrix.util.InvoiceChecker.ExpectedInvoiceItemCheck)1 InternalCallContext (org.killbill.billing.callcontext.InternalCallContext)1 BillingPeriod (org.killbill.billing.catalog.api.BillingPeriod)1 PhaseType (org.killbill.billing.catalog.api.PhaseType)1 PlanPhase (org.killbill.billing.catalog.api.PlanPhase)1 PlanPhaseSpecifier (org.killbill.billing.catalog.api.PlanPhaseSpecifier)1 ProductCategory (org.killbill.billing.catalog.api.ProductCategory)1 BlockingState (org.killbill.billing.entitlement.api.BlockingState)1