Search in sources :

Example 26 with Entitlement

use of org.killbill.billing.entitlement.api.Entitlement in project killbill by killbill.

the class TestDefaultInternalBillingApi method testUnblockThenBlockBlockingStatesWithSameEffectiveDate.

// See https://github.com/killbill/killbill/commit/92042843e38a67f75495b207385e4c1f9ca60990#commitcomment-4749967
@Test(groups = "slow", description = "Check unblock then block states with same effective date are correctly handled", invocationCount = 10)
public void testUnblockThenBlockBlockingStatesWithSameEffectiveDate() throws Exception {
    final LocalDate initialDate = new LocalDate(2013, 8, 7);
    clock.setDay(initialDate);
    final Account account = createAccount(getAccountData(7));
    testListener.pushExpectedEvents(NextEvent.CREATE, NextEvent.BLOCK);
    final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
    final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, null, null, false, ImmutableList.<PluginProperty>of(), callContext);
    final SubscriptionBase subscription = subscriptionInternalApi.getSubscriptionFromId(entitlement.getId(), internalCallContext);
    assertListenerStatus();
    final DateTime block1Date = clock.getUTCNow();
    testListener.pushExpectedEvents(NextEvent.BLOCK);
    final DefaultBlockingState state1 = new DefaultBlockingState(account.getId(), BlockingStateType.ACCOUNT, DefaultEntitlementApi.ENT_STATE_BLOCKED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, true, block1Date);
    blockingInternalApi.setBlockingState(state1, internalCallContext);
    clock.addDays(1);
    final DateTime block2Date = clock.getUTCNow();
    testListener.pushExpectedEvents(NextEvent.BLOCK, NextEvent.BLOCK);
    final DefaultBlockingState state2 = new DefaultBlockingState(account.getId(), BlockingStateType.ACCOUNT, DefaultEntitlementApi.ENT_STATE_CLEAR, EntitlementService.ENTITLEMENT_SERVICE_NAME, false, false, false, block2Date);
    blockingInternalApi.setBlockingState(state2, internalCallContext);
    // Same date
    final DefaultBlockingState state3 = new DefaultBlockingState(account.getId(), BlockingStateType.ACCOUNT, DefaultEntitlementApi.ENT_STATE_BLOCKED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, true, block2Date);
    blockingInternalApi.setBlockingState(state3, internalCallContext);
    assertListenerStatus();
    // Nothing should happen
    clock.addDays(3);
    assertListenerStatus();
    // Expected blocking duration:
    // * 2013-08-07 to now [2013-08-07 to 2013-08-08 then 2013-08-08 to now]
    final List<BillingEvent> events = ImmutableList.<BillingEvent>copyOf(billingInternalApi.getBillingEventsForAccountAndUpdateAccountBCD(account.getId(), null, internalCallContext));
    Assert.assertEquals(events.size(), 2);
    Assert.assertEquals(events.get(0).getTransitionType(), SubscriptionBaseTransitionType.CREATE);
    Assert.assertEquals(events.get(0).getEffectiveDate(), subscription.getStartDate());
    Assert.assertEquals(events.get(1).getTransitionType(), SubscriptionBaseTransitionType.START_BILLING_DISABLED);
    Assert.assertEquals(events.get(1).getEffectiveDate(), block1Date);
}
Also used : PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) Account(org.killbill.billing.account.api.Account) BillingEvent(org.killbill.billing.junction.BillingEvent) Entitlement(org.killbill.billing.entitlement.api.Entitlement) LocalDate(org.joda.time.LocalDate) DateTime(org.joda.time.DateTime) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) Test(org.testng.annotations.Test)

Example 27 with Entitlement

use of org.killbill.billing.entitlement.api.Entitlement in project killbill by killbill.

the class DefaultEntitlementService method processEntitlementNotification.

private void processEntitlementNotification(final EntitlementNotificationKey key, final InternalCallContext internalCallContext, final CallContext callContext) {
    final Entitlement entitlement;
    try {
        entitlement = entitlementInternalApi.getEntitlementForId(key.getEntitlementId(), internalCallContext);
    } catch (final EntitlementApiException e) {
        log.error("Error retrieving entitlementId='{}'", key.getEntitlementId(), e);
        return;
    }
    if (!(entitlement instanceof DefaultEntitlement)) {
        log.error("Error retrieving entitlementId='{}', unexpected entitlement className='{}'", key.getEntitlementId(), entitlement.getClass().getName());
        return;
    }
    final EntitlementNotificationKeyAction entitlementNotificationKeyAction = key.getEntitlementNotificationKeyAction();
    try {
        if (EntitlementNotificationKeyAction.CHANGE.equals(entitlementNotificationKeyAction) || EntitlementNotificationKeyAction.CANCEL.equals(entitlementNotificationKeyAction)) {
            blockAddOnsIfRequired(key, (DefaultEntitlement) entitlement, callContext, internalCallContext);
        } else if (EntitlementNotificationKeyAction.PAUSE.equals(entitlementNotificationKeyAction)) {
            entitlementInternalApi.pause(key.getBundleId(), internalCallContext.toLocalDate(key.getEffectiveDate()), ImmutableList.<PluginProperty>of(), internalCallContext);
        } else if (EntitlementNotificationKeyAction.RESUME.equals(entitlementNotificationKeyAction)) {
            entitlementInternalApi.resume(key.getBundleId(), internalCallContext.toLocalDate(key.getEffectiveDate()), ImmutableList.<PluginProperty>of(), internalCallContext);
        }
    } catch (final EntitlementApiException e) {
        log.error("Error processing event for entitlementId='{}'", entitlement.getId(), e);
    }
}
Also used : EntitlementNotificationKeyAction(org.killbill.billing.entitlement.engine.core.EntitlementNotificationKeyAction) PluginProperty(org.killbill.billing.payment.api.PluginProperty) DefaultEntitlement(org.killbill.billing.entitlement.api.DefaultEntitlement) EntitlementApiException(org.killbill.billing.entitlement.api.EntitlementApiException) DefaultEntitlement(org.killbill.billing.entitlement.api.DefaultEntitlement) Entitlement(org.killbill.billing.entitlement.api.Entitlement)

Example 28 with Entitlement

use of org.killbill.billing.entitlement.api.Entitlement in project killbill by killbill.

the class DefaultEntitlementApiBase method getAllEntitlementsForAccount.

public AccountEntitlements getAllEntitlementsForAccount(final InternalTenantContext tenantContext) throws EntitlementApiException {
    final AccountEventsStreams accountEventsStreams = eventsStreamBuilder.buildForAccount(tenantContext);
    final Map<UUID, Collection<Entitlement>> entitlementsPerBundle = new HashMap<UUID, Collection<Entitlement>>();
    for (final UUID bundleId : accountEventsStreams.getEventsStreams().keySet()) {
        if (entitlementsPerBundle.get(bundleId) == null) {
            entitlementsPerBundle.put(bundleId, new LinkedList<Entitlement>());
        }
        for (final EventsStream eventsStream : accountEventsStreams.getEventsStreams().get(bundleId)) {
            final Entitlement entitlement = new DefaultEntitlement(eventsStream, eventsStreamBuilder, entitlementApi, pluginExecution, blockingStateDao, subscriptionInternalApi, checker, notificationQueueService, entitlementUtils, dateHelper, clock, securityApi, tenantContext, internalCallContextFactory);
            entitlementsPerBundle.get(bundleId).add(entitlement);
        }
    }
    return new DefaultAccountEntitlements(accountEventsStreams, entitlementsPerBundle);
}
Also used : HashMap(java.util.HashMap) EventsStream(org.killbill.billing.entitlement.EventsStream) DefaultEntitlement(org.killbill.billing.entitlement.api.DefaultEntitlement) Collection(java.util.Collection) AccountEventsStreams(org.killbill.billing.entitlement.AccountEventsStreams) DefaultEntitlement(org.killbill.billing.entitlement.api.DefaultEntitlement) Entitlement(org.killbill.billing.entitlement.api.Entitlement) UUID(java.util.UUID)

Example 29 with Entitlement

use of org.killbill.billing.entitlement.api.Entitlement in project killbill by killbill.

the class DefaultEntitlementInternalApi method cancel.

@Override
public void cancel(final Iterable<Entitlement> entitlements, @Nullable final LocalDate effectiveDate, final BillingActionPolicy billingPolicy, final Iterable<PluginProperty> properties, final InternalCallContext internalCallContext) throws EntitlementApiException {
    if (!entitlements.iterator().hasNext()) {
        return;
    }
    int bcd = 0;
    DateTimeZone accountTimeZone = null;
    try {
        bcd = accountApi.getBCD(entitlements.iterator().next().getAccountId(), internalCallContext);
        accountTimeZone = accountApi.getImmutableAccountDataByRecordId(internalCallContext.getAccountRecordId(), internalCallContext).getTimeZone();
    } catch (final AccountApiException e) {
        throw new EntitlementApiException(e);
    }
    Preconditions.checkState(bcd > 0 && accountTimeZone != null, "Unexpected condition where account info could not be retrieved");
    final CallContext callContext = internalCallContextFactory.createCallContext(internalCallContext);
    final ImmutableMap.Builder<BlockingState, Optional<UUID>> blockingStates = new ImmutableMap.Builder<BlockingState, Optional<UUID>>();
    final Map<DateTime, Collection<NotificationEvent>> notificationEvents = new HashMap<DateTime, Collection<NotificationEvent>>();
    final Collection<EntitlementContext> pluginContexts = new LinkedList<EntitlementContext>();
    final List<WithEntitlementPlugin> callbacks = new LinkedList<WithEntitlementPlugin>();
    final List<SubscriptionBase> subscriptions = new LinkedList<SubscriptionBase>();
    for (final Entitlement entitlement : entitlements) {
        if (entitlement.getState() == EntitlementState.CANCELLED) {
            // If subscription has already been cancelled, we ignore and carry on
            continue;
        }
        final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(entitlement.getBundleId(), entitlement.getExternalKey(), null, effectiveDate, null, false);
        final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
        baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementWithAddOnsSpecifier);
        final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CANCEL_SUBSCRIPTION, entitlement.getAccountId(), null, baseEntitlementWithAddOnsSpecifierList, billingPolicy, properties, callContext);
        pluginContexts.add(pluginContext);
        final WithEntitlementPlugin<Entitlement> cancelEntitlementWithPlugin = new WithDateOverrideBillingPolicyEntitlementCanceler((DefaultEntitlement) entitlement, blockingStates, notificationEvents, callContext, internalCallContext);
        callbacks.add(cancelEntitlementWithPlugin);
        subscriptions.add(((DefaultEntitlement) entitlement).getSubscriptionBase());
    }
    final Callable<Void> preCallbacksCallback = new BulkSubscriptionBaseCancellation(subscriptions, billingPolicy, accountTimeZone, bcd, internalCallContext);
    pluginExecution.executeWithPlugin(preCallbacksCallback, callbacks, pluginContexts);
    // Record the new states first, then insert the notifications to avoid race conditions
    blockingStateDao.setBlockingStatesAndPostBlockingTransitionEvent(blockingStates.build(), internalCallContext);
    for (final DateTime effectiveDateForNotification : notificationEvents.keySet()) {
        for (final NotificationEvent notificationEvent : notificationEvents.get(effectiveDateForNotification)) {
            recordFutureNotification(effectiveDateForNotification, notificationEvent, internalCallContext);
        }
    }
}
Also used : HashMap(java.util.HashMap) WithEntitlementPlugin(org.killbill.billing.entitlement.api.EntitlementPluginExecution.WithEntitlementPlugin) EventsStreamBuilder(org.killbill.billing.entitlement.engine.core.EventsStreamBuilder) ArrayList(java.util.ArrayList) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) BlockingState(org.killbill.billing.entitlement.api.BlockingState) DateTime(org.joda.time.DateTime) SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) AccountApiException(org.killbill.billing.account.api.AccountApiException) BaseEntitlementWithAddOnsSpecifier(org.killbill.billing.entitlement.api.BaseEntitlementWithAddOnsSpecifier) DefaultBaseEntitlementWithAddOnsSpecifier(org.killbill.billing.entitlement.api.DefaultBaseEntitlementWithAddOnsSpecifier) UUID(java.util.UUID) DefaultEntitlementContext(org.killbill.billing.entitlement.api.DefaultEntitlementContext) EntitlementContext(org.killbill.billing.entitlement.plugin.api.EntitlementContext) DefaultBaseEntitlementWithAddOnsSpecifier(org.killbill.billing.entitlement.api.DefaultBaseEntitlementWithAddOnsSpecifier) Optional(com.google.common.base.Optional) EntitlementApiException(org.killbill.billing.entitlement.api.EntitlementApiException) NotificationEvent(org.killbill.notificationq.api.NotificationEvent) CallContext(org.killbill.billing.util.callcontext.CallContext) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) DateTimeZone(org.joda.time.DateTimeZone) ImmutableMap(com.google.common.collect.ImmutableMap) LinkedList(java.util.LinkedList) Collection(java.util.Collection) DefaultEntitlement(org.killbill.billing.entitlement.api.DefaultEntitlement) Entitlement(org.killbill.billing.entitlement.api.Entitlement) DefaultEntitlementContext(org.killbill.billing.entitlement.api.DefaultEntitlementContext)

Example 30 with Entitlement

use of org.killbill.billing.entitlement.api.Entitlement in project killbill by killbill.

the class TestWithTimeZones method testCancellationFrom_PST_to_PDT.

// Same test as previous test but this time going from PST -> PDT (somehow not too interesting in that direction because we start with
// an offset of 8 hours and then go through 7 hours so anyway we would stay in the same day.
@Test(groups = "slow")
public void testCancellationFrom_PST_to_PDT() throws Exception {
    clock.setTime(new DateTime("2015-02-01T08:01:01.000Z"));
    final DateTimeZone tz = DateTimeZone.forID("America/Los_Angeles");
    final AccountData accountData = new MockAccountBuilder().name(UUID.randomUUID().toString().substring(1, 8)).firstNameLength(6).email(UUID.randomUUID().toString().substring(1, 8)).phone(UUID.randomUUID().toString().substring(1, 8)).migrated(false).isNotifiedForInvoices(false).externalKey(UUID.randomUUID().toString().substring(1, 8)).billingCycleDayLocal(1).currency(Currency.USD).paymentMethodId(UUID.randomUUID()).timeZone(tz).build();
    final Account account = createAccountWithNonOsgiPaymentMethod(accountData);
    accountChecker.checkAccount(account.getId(), accountData, callContext);
    busHandler.pushExpectedEvents(NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
    final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Blowdart", BillingPeriod.MONTHLY, "notrial", null);
    Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, "Something", ImmutableList.<PlanPhasePriceOverride>of(), null, null, false, ImmutableList.<PluginProperty>of(), callContext);
    assertListenerStatus();
    // Cancel the next month specifying just a LocalDate
    final LocalDate cancellationDate = new LocalDate("2015-03-01", tz);
    entitlement = entitlement.cancelEntitlementWithDate(cancellationDate, true, ImmutableList.<PluginProperty>of(), callContext);
    // Verify first entitlement is correctly cancelled on the right date
    Assert.assertEquals(entitlement.getEffectiveEndDate(), cancellationDate);
    // We now move the clock to the date of the cancellation  which match the cancellation day from the client point of view
    busHandler.pushExpectedEvents(NextEvent.CANCEL, NextEvent.BLOCK, NextEvent.NULL_INVOICE, NextEvent.NULL_INVOICE);
    clock.setTime(new DateTime("2015-03-01T08:01:02"));
    assertListenerStatus();
    // Verify second that there was no repair (so the cancellation did correctly happen on the "2015-12-01"
    final List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), false, callContext);
    Assert.assertEquals(invoices.size(), 1);
}
Also used : PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) Account(org.killbill.billing.account.api.Account) PluginProperty(org.killbill.billing.payment.api.PluginProperty) MockAccountBuilder(org.killbill.billing.mock.MockAccountBuilder) Invoice(org.killbill.billing.invoice.api.Invoice) AccountData(org.killbill.billing.account.api.AccountData) DefaultEntitlement(org.killbill.billing.entitlement.api.DefaultEntitlement) Entitlement(org.killbill.billing.entitlement.api.Entitlement) LocalDate(org.joda.time.LocalDate) DateTime(org.joda.time.DateTime) DateTimeZone(org.joda.time.DateTimeZone) Test(org.testng.annotations.Test)

Aggregations

Entitlement (org.killbill.billing.entitlement.api.Entitlement)47 LocalDate (org.joda.time.LocalDate)32 Test (org.testng.annotations.Test)30 Account (org.killbill.billing.account.api.Account)28 PlanPhaseSpecifier (org.killbill.billing.catalog.api.PlanPhaseSpecifier)27 DefaultEntitlement (org.killbill.billing.entitlement.api.DefaultEntitlement)23 ArrayList (java.util.ArrayList)12 DateTime (org.joda.time.DateTime)12 BigDecimal (java.math.BigDecimal)10 EntitlementApiException (org.killbill.billing.entitlement.api.EntitlementApiException)10 PluginProperty (org.killbill.billing.payment.api.PluginProperty)10 UUID (java.util.UUID)9 CallContext (org.killbill.billing.util.callcontext.CallContext)9 ApiOperation (io.swagger.annotations.ApiOperation)8 ApiResponses (io.swagger.annotations.ApiResponses)8 Produces (javax.ws.rs.Produces)8 AccountData (org.killbill.billing.account.api.AccountData)8 ExpectedInvoiceItemCheck (org.killbill.billing.beatrix.util.InvoiceChecker.ExpectedInvoiceItemCheck)8 Subscription (org.killbill.billing.entitlement.api.Subscription)8 Invoice (org.killbill.billing.invoice.api.Invoice)8