Search in sources :

Example 36 with SubscriptionBase

use of org.killbill.billing.subscription.api.SubscriptionBase in project killbill by killbill.

the class DefaultSubscriptionBaseApiService method createPlansWithAddOns.

@Override
public List<SubscriptionBaseWithAddOns> createPlansWithAddOns(final UUID accountId, final Iterable<SubscriptionAndAddOnsSpecifier> subscriptionsAndAddOns, final SubscriptionCatalog kbCatalog, final CallContext context) throws SubscriptionBaseApiException {
    final Map<UUID, List<SubscriptionBaseEvent>> eventsMap = new HashMap<UUID, List<SubscriptionBaseEvent>>();
    final Collection<List<SubscriptionBase>> subscriptionBaseAndAddOnsList = new ArrayList<List<SubscriptionBase>>();
    final InternalCallContext internalCallContext = createCallContextFromAccountId(accountId, context);
    try {
        final List<SubscriptionBaseWithAddOns> allSubscriptions = new ArrayList<SubscriptionBaseWithAddOns>();
        for (final SubscriptionAndAddOnsSpecifier subscriptionAndAddOns : subscriptionsAndAddOns) {
            final List<SubscriptionBase> subscriptionBaseList = new ArrayList<SubscriptionBase>();
            createEvents(subscriptionAndAddOns.getSubscriptionSpecifiers(), context, eventsMap, subscriptionBaseList, kbCatalog);
            subscriptionBaseAndAddOnsList.add(subscriptionBaseList);
            final SubscriptionBaseWithAddOns subscriptionBaseWithAddOns = new DefaultSubscriptionBaseWithAddOns(subscriptionAndAddOns.getBundle(), subscriptionBaseList);
            allSubscriptions.add(subscriptionBaseWithAddOns);
        }
        final List<SubscriptionBaseEvent> events = dao.createSubscriptionsWithAddOns(allSubscriptions, eventsMap, kbCatalog, internalCallContext);
        final ListMultimap<UUID, SubscriptionBaseEvent> eventsBySubscription = ArrayListMultimap.<UUID, SubscriptionBaseEvent>create();
        for (final SubscriptionBaseEvent event : events) {
            eventsBySubscription.put(event.getSubscriptionId(), event);
        }
        for (final List<SubscriptionBase> subscriptions : subscriptionBaseAndAddOnsList) {
            for (final SubscriptionBase input : subscriptions) {
                ((DefaultSubscriptionBase) input).rebuildTransitions(eventsBySubscription.get(input.getId()), kbCatalog);
            }
        }
        return allSubscriptions;
    } catch (final CatalogApiException e) {
        throw new SubscriptionBaseApiException(e);
    }
}
Also used : SubscriptionBaseWithAddOns(org.killbill.billing.subscription.api.SubscriptionBaseWithAddOns) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) List(java.util.List) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) LinkedList(java.util.LinkedList) UUID(java.util.UUID) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent)

Example 37 with SubscriptionBase

use of org.killbill.billing.subscription.api.SubscriptionBase in project killbill by killbill.

the class DefaultSubscriptionBaseCreateApi method prepareSubscriptionAndAddOnsSpecifier.

private void prepareSubscriptionAndAddOnsSpecifier(final Collection<SubscriptionAndAddOnsSpecifier> subscriptionAndAddOns, final SubscriptionBaseWithAddOnsSpecifier subscriptionBaseWithAddOnsSpecifier, final boolean renameCancelledBundleIfExist, final SubscriptionCatalog catalog, final AddonUtils addonUtils, final CacheController<UUID, UUID> accountIdCacheController, final CallContext callContext, final InternalCallContext context) throws SubscriptionBaseApiException, CatalogApiException {
    SubscriptionBaseBundle bundle = getBundleWithSanity(subscriptionBaseWithAddOnsSpecifier, catalog, callContext, context);
    final DateTime billingRequestedDateRaw = (subscriptionBaseWithAddOnsSpecifier.getBillingEffectiveDate() != null) ? context.toUTCDateTime(subscriptionBaseWithAddOnsSpecifier.getBillingEffectiveDate()) : context.getCreatedDate();
    final SubscriptionBase baseSubscription;
    final DateTime billingRequestedDate;
    if (bundle != null) {
        baseSubscription = dao.getBaseSubscription(bundle.getId(), catalog, context);
        billingRequestedDate = computeActualBillingRequestedDate(bundle, billingRequestedDateRaw, baseSubscription, catalog, context);
    } else {
        baseSubscription = null;
        billingRequestedDate = billingRequestedDateRaw;
    }
    final List<EntitlementSpecifier> reorderedSpecifiers = new ArrayList<EntitlementSpecifier>();
    final List<Plan> createdOrRetrievedPlans = new ArrayList<Plan>();
    final boolean hasBaseOrStandalonePlanSpecifier = createPlansIfNeededAndReorderBPOrStandaloneSpecFirstWithSanity(subscriptionBaseWithAddOnsSpecifier, catalog, billingRequestedDate, reorderedSpecifiers, createdOrRetrievedPlans, callContext);
    if (hasBaseOrStandalonePlanSpecifier && baseSubscription != null) {
        throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_BP_EXISTS, bundle.getExternalKey());
    }
    if (bundle == null && hasBaseOrStandalonePlanSpecifier) {
        bundle = createBundleForAccount(callContext.getAccountId(), subscriptionBaseWithAddOnsSpecifier.getBundleExternalKey(), renameCancelledBundleIfExist, catalog, accountIdCacheController, context);
    } else if (bundle == null) {
        log.warn("Invalid specifier: {}", subscriptionBaseWithAddOnsSpecifier);
        throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_NO_BP, subscriptionBaseWithAddOnsSpecifier.getBundleExternalKey());
    }
    final List<SubscriptionSpecifier> subscriptionSpecifiers = verifyAndBuildSubscriptionSpecifiers(bundle, hasBaseOrStandalonePlanSpecifier, reorderedSpecifiers, createdOrRetrievedPlans, subscriptionBaseWithAddOnsSpecifier.isMigrated(), billingRequestedDate, catalog, addonUtils, callContext, context);
    final SubscriptionAndAddOnsSpecifier subscriptionAndAddOnsSpecifier = new SubscriptionAndAddOnsSpecifier(bundle, billingRequestedDate, subscriptionSpecifiers);
    subscriptionAndAddOns.add(subscriptionAndAddOnsSpecifier);
}
Also used : SubscriptionSpecifier(org.killbill.billing.subscription.api.user.SubscriptionSpecifier) ArrayList(java.util.ArrayList) SubscriptionAndAddOnsSpecifier(org.killbill.billing.subscription.api.user.SubscriptionAndAddOnsSpecifier) Plan(org.killbill.billing.catalog.api.Plan) DateTime(org.joda.time.DateTime) SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) DefaultSubscriptionBase(org.killbill.billing.subscription.api.user.DefaultSubscriptionBase) EntitlementSpecifier(org.killbill.billing.entitlement.api.EntitlementSpecifier) SubscriptionBaseBundle(org.killbill.billing.subscription.api.user.SubscriptionBaseBundle) SubscriptionBaseApiException(org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)

Example 38 with SubscriptionBase

use of org.killbill.billing.subscription.api.SubscriptionBase in project killbill by killbill.

the class TestOverdueWithSubscriptionCancellation method testCheckSubscriptionCancellationWithMultipleBundles.

@Test(groups = "slow", retryAnalyzer = FlakyRetryAnalyzer.class)
public void testCheckSubscriptionCancellationWithMultipleBundles() throws Exception {
    // 2012-05-01T00:03:53.000Z
    clock.setTime(new DateTime(2012, 5, 1, 0, 3, 42, 0));
    setupAccount();
    // Set next invoice to fail and create subscription
    paymentPlugin.makeAllInvoicesFailWithError(true);
    final DefaultEntitlement baseEntitlement = createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey", productName, ProductCategory.BASE, term, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
    bundle = subscriptionApi.getSubscriptionBundle(baseEntitlement.getBundleId(), callContext);
    invoiceChecker.checkInvoice(account.getId(), 1, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 1), null, InvoiceItemType.FIXED, new BigDecimal("0")));
    invoiceChecker.checkChargedThroughDate(baseEntitlement.getId(), new LocalDate(2012, 5, 1), callContext);
    final DefaultEntitlement baseEntitlement2 = createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey2", productName, ProductCategory.BASE, term, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
    final SubscriptionBundle bundle2 = subscriptionApi.getSubscriptionBundle(baseEntitlement.getBundleId(), callContext);
    invoiceChecker.checkInvoice(account.getId(), 2, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 1), null, InvoiceItemType.FIXED, new BigDecimal("0")));
    invoiceChecker.checkChargedThroughDate(baseEntitlement2.getId(), new LocalDate(2012, 5, 1), callContext);
    final DefaultEntitlement baseEntitlement3 = createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey3", productName, ProductCategory.BASE, term, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
    final SubscriptionBundle bundle3 = subscriptionApi.getSubscriptionBundle(baseEntitlement.getBundleId(), callContext);
    invoiceChecker.checkInvoice(account.getId(), 3, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 1), null, InvoiceItemType.FIXED, new BigDecimal("0")));
    invoiceChecker.checkChargedThroughDate(baseEntitlement2.getId(), new LocalDate(2012, 5, 1), callContext);
    // Cancel bundle 2 one day after (2012-05-02)
    clock.addDays(1);
    cancelEntitlementAndCheckForCompletion(baseEntitlement2, NextEvent.BLOCK, NextEvent.CANCEL, NextEvent.NULL_INVOICE);
    final SubscriptionBase cancelledBaseSubscription2 = ((DefaultEntitlement) entitlementApi.getEntitlementForId(baseEntitlement2.getId(), callContext)).getSubscriptionBase();
    assertTrue(cancelledBaseSubscription2.getState() == EntitlementState.CANCELLED);
    // DAY 30 have to get out of trial before first payment (2012-05-31)
    addDaysAndCheckForCompletion(29, NextEvent.PHASE, NextEvent.PHASE, NextEvent.NULL_INVOICE, NextEvent.INVOICE, NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR);
    invoiceChecker.checkInvoice(account.getId(), 4, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 31), new LocalDate(2012, 6, 30), InvoiceItemType.RECURRING, new BigDecimal("249.95")), new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 31), new LocalDate(2012, 6, 30), InvoiceItemType.RECURRING, new BigDecimal("249.95")));
    invoiceChecker.checkChargedThroughDate(baseEntitlement.getId(), new LocalDate(2012, 6, 30), callContext);
    // Should still be in clear state
    checkODState(OverdueWrapper.CLEAR_STATE_NAME);
    // DAY 36 (2012-06-06)-- RIGHT AFTER OD1 (two block events, for the cancellation and the OD1 state)
    // One BLOCK event is for the overdue state transition
    // The 2 other BLOCK are for the entitlement blocking states for both baseEntitlement and baseEntitlement3
    addDaysAndCheckForCompletion(6, NextEvent.BLOCK, NextEvent.BLOCK, NextEvent.BLOCK, NextEvent.CANCEL, NextEvent.CANCEL, NextEvent.INVOICE, NextEvent.INVOICE_ADJUSTMENT);
    // Should be in OD1
    checkODState("OD1");
    final SubscriptionBase cancelledBaseSubscription = ((DefaultEntitlement) entitlementApi.getEntitlementForId(baseEntitlement.getId(), callContext)).getSubscriptionBase();
    assertTrue(cancelledBaseSubscription.getState() == EntitlementState.CANCELLED);
    final SubscriptionBase cancelledBaseEntitlement3 = ((DefaultEntitlement) entitlementApi.getEntitlementForId(baseEntitlement3.getId(), callContext)).getSubscriptionBase();
    assertTrue(cancelledBaseEntitlement3.getState() == EntitlementState.CANCELLED);
}
Also used : SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) SubscriptionBundle(org.killbill.billing.entitlement.api.SubscriptionBundle) DefaultEntitlement(org.killbill.billing.entitlement.api.DefaultEntitlement) ExpectedInvoiceItemCheck(org.killbill.billing.beatrix.util.InvoiceChecker.ExpectedInvoiceItemCheck) LocalDate(org.joda.time.LocalDate) DateTime(org.joda.time.DateTime) BigDecimal(java.math.BigDecimal) Test(org.testng.annotations.Test)

Example 39 with SubscriptionBase

use of org.killbill.billing.subscription.api.SubscriptionBase in project killbill by killbill.

the class TestNextBillingDatePoster method testDryRunReInsertion.

@Test(groups = "slow")
public void testDryRunReInsertion() throws Exception {
    final Account account = invoiceUtil.createAccount(callContext);
    final Long accountRecordId = nonEntityDao.retrieveAccountRecordIdFromObject(account.getId(), ObjectType.ACCOUNT, null);
    final LocalDate notificationDate = clock.getUTCToday().plusDays(30);
    final SubscriptionBase subscription = invoiceUtil.createSubscription();
    final UUID subscriptionId = subscription.getId();
    final FutureAccountNotifications futureAccountNotifications = createFutureAccountNotifications(subscriptionId, notificationDate);
    invoiceDao.setFutureAccountNotificationsForEmptyInvoice(account.getId(), futureAccountNotifications, internalCallContext);
    invoiceDao.setFutureAccountNotificationsForEmptyInvoice(account.getId(), futureAccountNotifications, internalCallContext);
    final NotificationQueue nextBillingQueue = notificationQueueService.getNotificationQueue(KILLBILL_SERVICES.INVOICE_SERVICE.getServiceName(), DefaultNextBillingDateNotifier.NEXT_BILLING_DATE_NOTIFIER_QUEUE);
    final Iterable<NotificationEventWithMetadata<NextBillingDateNotificationKey>> futureNotifications = nextBillingQueue.getFutureNotificationForSearchKeys(accountRecordId, internalCallContext.getTenantRecordId());
    final ImmutableList<NotificationEventWithMetadata<NextBillingDateNotificationKey>> futureNotificationsList = ImmutableList.copyOf(futureNotifications);
    Assert.assertEquals(futureNotificationsList.size(), 1);
    // We expect only one notification for which effectiveDate matches our original effectiveDate (conversion DateTime -> LocalDate -> DateTime)
    final NotificationEventWithMetadata<NextBillingDateNotificationKey> notification = futureNotificationsList.get(0);
    Assert.assertEquals(notification.getEffectiveDate(), internalCallContext.toUTCDateTime(notificationDate));
    final Iterable<UUID> uuidKeys = notification.getEvent().getUuidKeys();
    Assert.assertFalse(Iterables.isEmpty(uuidKeys));
    final List<UUID> uuidKeysList = ImmutableList.copyOf(uuidKeys);
    Assert.assertEquals(uuidKeysList.size(), 1);
    Assert.assertEquals(uuidKeysList.get(0), subscriptionId);
}
Also used : Account(org.killbill.billing.account.api.Account) FutureAccountNotifications(org.killbill.billing.invoice.InvoiceDispatcher.FutureAccountNotifications) NotificationQueue(org.killbill.notificationq.api.NotificationQueue) LocalDate(org.joda.time.LocalDate) SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) NotificationEventWithMetadata(org.killbill.notificationq.api.NotificationEventWithMetadata) UUID(java.util.UUID) Test(org.testng.annotations.Test)

Example 40 with SubscriptionBase

use of org.killbill.billing.subscription.api.SubscriptionBase in project killbill by killbill.

the class TestUserApiError method testChangeSubscriptionWithPolicy.

@Test(groups = "fast")
public void testChangeSubscriptionWithPolicy() throws Exception {
    final SubscriptionBase subscription = testUtil.createSubscription(bundle, "Shotgun", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME);
    try {
        final PlanPhaseSpecifier planPhaseSpecifier = new PlanPhaseSpecifier("Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME);
        subscription.changePlanWithPolicy(new DefaultEntitlementSpecifier(planPhaseSpecifier), BillingActionPolicy.ILLEGAL, callContext);
        Assert.fail("Call changePlanWithPolicy should have failed");
    } catch (final SubscriptionBaseError error) {
        assertTrue(true);
        assertEquals(subscriptionInternalApi.getSubscriptionFromId(subscription.getId(), internalCallContext).getCurrentPlan().getRecurringBillingPeriod(), BillingPeriod.ANNUAL);
    }
    // Assume the call takes less than a second
    final PlanPhaseSpecifier planPhaseSpecifier = new PlanPhaseSpecifier("Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME);
    assertEquals(DefaultClock.truncateMs(subscription.changePlanWithPolicy(new DefaultEntitlementSpecifier(planPhaseSpecifier), BillingActionPolicy.IMMEDIATE, callContext)), DefaultClock.truncateMs(clock.getUTCNow()));
    assertEquals(subscriptionInternalApi.getSubscriptionFromId(subscription.getId(), internalCallContext).getCurrentPlan().getRecurringBillingPeriod(), BillingPeriod.MONTHLY);
}
Also used : SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) DefaultEntitlementSpecifier(org.killbill.billing.entitlement.api.DefaultEntitlementSpecifier) SubscriptionBaseError(org.killbill.billing.subscription.exceptions.SubscriptionBaseError) Test(org.testng.annotations.Test)

Aggregations

SubscriptionBase (org.killbill.billing.subscription.api.SubscriptionBase)120 Test (org.testng.annotations.Test)47 UUID (java.util.UUID)46 DateTime (org.joda.time.DateTime)40 Plan (org.killbill.billing.catalog.api.Plan)37 ArrayList (java.util.ArrayList)35 LocalDate (org.joda.time.LocalDate)33 DefaultSubscriptionBase (org.killbill.billing.subscription.api.user.DefaultSubscriptionBase)32 BillingEvent (org.killbill.billing.junction.BillingEvent)30 PlanPhase (org.killbill.billing.catalog.api.PlanPhase)26 MockPlan (org.killbill.billing.catalog.MockPlan)24 MockPlanPhase (org.killbill.billing.catalog.MockPlanPhase)24 MockBillingEventSet (org.killbill.billing.invoice.MockBillingEventSet)23 SubscriptionBaseApiException (org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)23 BigDecimal (java.math.BigDecimal)22 LinkedList (java.util.LinkedList)21 Invoice (org.killbill.billing.invoice.api.Invoice)21 AccountInvoices (org.killbill.billing.invoice.optimizer.InvoiceOptimizerBase.AccountInvoices)21 BillingEventSet (org.killbill.billing.junction.BillingEventSet)21 DefaultInvoice (org.killbill.billing.invoice.model.DefaultInvoice)20