Search in sources :

Example 26 with SubscriptionBase

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

the class DefaultEntitlementApiBase method resume.

public void resume(final UUID bundleId, @Nullable final LocalDate localEffectiveDate, final Iterable<PluginProperty> properties, final InternalCallContext internalCallContext) throws EntitlementApiException {
    final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(bundleId, null, null, localEffectiveDate, localEffectiveDate, false);
    final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
    baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementWithAddOnsSpecifier);
    final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.RESUME_BUNDLE, null, null, baseEntitlementWithAddOnsSpecifierList, null, properties, internalCallContextFactory.createCallContext(internalCallContext));
    final WithEntitlementPlugin<Void> resumeWithPlugin = new WithEntitlementPlugin<Void>() {

        @Override
        public Void doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
            try {
                final SubscriptionBase baseSubscription = subscriptionInternalApi.getBaseSubscription(bundleId, internalCallContext);
                blockUnblockBundle(bundleId, DefaultEntitlementApi.ENT_STATE_CLEAR, KILLBILL_SERVICES.ENTITLEMENT_SERVICE.getServiceName(), localEffectiveDate, false, false, false, baseSubscription, internalCallContext);
            } catch (SubscriptionBaseApiException e) {
                throw new EntitlementApiException(e);
            }
            return null;
        }
    };
    pluginExecution.executeWithPlugin(resumeWithPlugin, pluginContext);
}
Also used : WithEntitlementPlugin(org.killbill.billing.entitlement.api.EntitlementPluginExecution.WithEntitlementPlugin) ArrayList(java.util.ArrayList) EntitlementApiException(org.killbill.billing.entitlement.api.EntitlementApiException) DefaultEntitlementApi(org.killbill.billing.entitlement.api.DefaultEntitlementApi) EntitlementApi(org.killbill.billing.entitlement.api.EntitlementApi) SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) BaseEntitlementWithAddOnsSpecifier(org.killbill.billing.entitlement.api.BaseEntitlementWithAddOnsSpecifier) DefaultBaseEntitlementWithAddOnsSpecifier(org.killbill.billing.entitlement.api.DefaultBaseEntitlementWithAddOnsSpecifier) DefaultEntitlementContext(org.killbill.billing.entitlement.api.DefaultEntitlementContext) DefaultBaseEntitlementWithAddOnsSpecifier(org.killbill.billing.entitlement.api.DefaultBaseEntitlementWithAddOnsSpecifier) DefaultEntitlementContext(org.killbill.billing.entitlement.api.DefaultEntitlementContext) EntitlementContext(org.killbill.billing.entitlement.plugin.api.EntitlementContext) SubscriptionBaseApiException(org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)

Example 27 with SubscriptionBase

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

the class SubscriptionEventOrdering method computeSubscriptionBaseEvents.

// Compute the initial stream of events based on the subscription base events
private LinkedList<SubscriptionEvent> computeSubscriptionBaseEvents(final Iterable<Entitlement> entitlements, final InternalTenantContext internalTenantContext) {
    final LinkedList<SubscriptionEvent> result = new LinkedList<SubscriptionEvent>();
    for (final Entitlement cur : entitlements) {
        Preconditions.checkState(cur instanceof DefaultEntitlement, "Entitlement %s is not a DefaultEntitlement", cur);
        final SubscriptionBase base = ((DefaultEntitlement) cur).getSubscriptionBase();
        final List<SubscriptionBaseTransition> baseTransitions = base.getAllTransitions();
        for (final SubscriptionBaseTransition tr : baseTransitions) {
            final List<SubscriptionEventType> eventTypes = toEventTypes(tr.getTransitionType());
            for (final SubscriptionEventType eventType : eventTypes) {
                final SubscriptionEvent event = toSubscriptionEvent(tr, eventType, internalTenantContext);
                insertSubscriptionEvent(event, result);
            }
        }
    }
    return result;
}
Also used : SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) SubscriptionBaseTransition(org.killbill.billing.subscription.api.user.SubscriptionBaseTransition) LinkedList(java.util.LinkedList)

Example 28 with SubscriptionBase

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

the class DefaultEntitlementApi method getDryRunStatusForChange.

@Override
public List<EntitlementAOStatusDryRun> getDryRunStatusForChange(final UUID bundleId, final String targetProductName, @Nullable final LocalDate effectiveDate, final TenantContext context) throws EntitlementApiException {
    final InternalTenantContext internalContext = internalCallContextFactory.createInternalTenantContext(bundleId, ObjectType.BUNDLE, context);
    try {
        final SubscriptionBase baseSubscription = subscriptionBaseInternalApi.getBaseSubscription(bundleId, internalContext);
        final UUID accountId = subscriptionBaseInternalApi.getAccountIdFromBundleId(bundleId, internalContext);
        final InternalTenantContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalTenantContext(accountId, context);
        final DateTime now = clock.getUTCNow();
        final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(effectiveDate, now, contextWithValidAccountRecordId);
        return subscriptionBaseInternalApi.getDryRunChangePlanStatus(baseSubscription.getId(), targetProductName, requestedDate, contextWithValidAccountRecordId);
    } catch (final SubscriptionBaseApiException e) {
        throw new EntitlementApiException(e);
    }
}
Also used : SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) InternalTenantContext(org.killbill.billing.callcontext.InternalTenantContext) UUID(java.util.UUID) DateTime(org.joda.time.DateTime) SubscriptionBaseApiException(org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)

Example 29 with SubscriptionBase

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

the class DefaultInternalBillingApi method addBillingEventsForBundles.

private void addBillingEventsForBundles(final ImmutableAccountData account, final DryRunArguments dryRunArguments, final InternalCallContext context, final DefaultBillingEventSet result, final Set<UUID> skipSubscriptionsSet, final Map<UUID, List<SubscriptionBase>> subscriptionsForAccount, final VersionedCatalog catalog, final List<Tag> tagsForAccount, final int currentAccountBCD) throws AccountApiException, CatalogApiException, SubscriptionBaseApiException {
    // want to tap into subscriptionBase logic, so we make up a bundleId
    if (dryRunArguments != null && dryRunArguments.getAction() == SubscriptionEventType.START_BILLING && dryRunArguments.getBundleId() == null) {
        final UUID fakeBundleId = UUIDs.randomUUID();
        final List<SubscriptionBase> subscriptions = subscriptionApi.getSubscriptionsForBundle(fakeBundleId, dryRunArguments, context);
        addBillingEventsForSubscription(account, subscriptions, null, currentAccountBCD, context, result, skipSubscriptionsSet, catalog);
    }
    for (final UUID bundleId : subscriptionsForAccount.keySet()) {
        final DryRunArguments dryRunArgumentsForBundle = (dryRunArguments != null && dryRunArguments.getBundleId() != null && dryRunArguments.getBundleId().equals(bundleId)) ? dryRunArguments : null;
        final List<SubscriptionBase> subscriptions;
        // In dryRun mode, optimization is intentionally left as is, since is not a common path.
        if (dryRunArgumentsForBundle == null || dryRunArgumentsForBundle.getAction() == null) {
            subscriptions = getSubscriptionsForAccountByBundleId(subscriptionsForAccount, bundleId);
        } else {
            subscriptions = subscriptionApi.getSubscriptionsForBundle(bundleId, dryRunArgumentsForBundle, context);
        }
        // Check if billing is off for the bundle
        final List<Tag> bundleTags = getTagsForObjectType(ObjectType.BUNDLE, tagsForAccount, bundleId);
        final boolean found_AUTO_INVOICING_OFF = is_AUTO_INVOICING_OFF(bundleTags);
        if (found_AUTO_INVOICING_OFF) {
            for (final SubscriptionBase subscription : subscriptions) {
                // billing is off so list sub ids in set to be excluded
                result.getSubscriptionIdsWithAutoInvoiceOff().add(subscription.getId());
            }
        } else {
            // billing is not off
            final SubscriptionBase baseSubscription = subscriptions != null && !subscriptions.isEmpty() ? subscriptions.get(0) : null;
            addBillingEventsForSubscription(account, subscriptions, baseSubscription, currentAccountBCD, context, result, skipSubscriptionsSet, catalog);
        }
    }
    // If dryRun is specified, we don't want to update the account BCD value, so we initialize the flag updatedAccountBCD to true
    if (currentAccountBCD == 0) {
        final Integer accountBCDCandidate = computeAccountBCD(result);
        if (accountBCDCandidate == null) {
            return;
        }
        // Because we now have computed the real BCD, we need to re-compute the BillingEvents BCD for ACCOUNT alignments (see BillCycleDayCalculator#calculateBcdForAlignment).
        // The code could maybe be optimized (no need to re-run the full function?), but since it's run once per account, it's probably not worth it.
        result.clear();
        addBillingEventsForBundles(account, dryRunArguments, context, result, skipSubscriptionsSet, subscriptionsForAccount, catalog, tagsForAccount, accountBCDCandidate);
        final boolean dryRunMode = dryRunArguments != null;
        if (!dryRunMode) {
            log.info("Setting account BCD='{}', accountId='{}'", accountBCDCandidate, account.getId());
            accountApi.updateBCD(account.getExternalKey(), accountBCDCandidate, context);
        }
    }
}
Also used : SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) DryRunArguments(org.killbill.billing.invoice.api.DryRunArguments) Tag(org.killbill.billing.util.tag.Tag) UUID(java.util.UUID)

Example 30 with SubscriptionBase

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

the class DefaultInternalBillingApi method addBillingEventsForSubscription.

private void addBillingEventsForSubscription(final ImmutableAccountData account, @Nullable final List<SubscriptionBase> subscriptions, final SubscriptionBase baseSubscription, final int currentAccountBCD, final InternalCallContext context, final DefaultBillingEventSet result, final Set<UUID> skipSubscriptionsSet, final VersionedCatalog catalog) throws SubscriptionBaseApiException, CatalogApiException {
    if (subscriptions == null) {
        return;
    }
    final Map<UUID, Integer> bcdCache = new HashMap<UUID, Integer>();
    for (final SubscriptionBase subscription : subscriptions) {
        // TODO Can we batch those ?
        final List<SubscriptionBillingEvent> billingTransitions = subscriptionApi.getSubscriptionBillingEvents(catalog, subscription, context);
        if (billingTransitions.isEmpty() || (billingTransitions.get(0).getType() != SubscriptionBaseTransitionType.CREATE && billingTransitions.get(0).getType() != SubscriptionBaseTransitionType.TRANSFER)) {
            log.warn("Skipping billing events for subscription " + subscription.getId() + ": Does not start with a valid CREATE transition");
            skipSubscriptionsSet.add(subscription.getId());
            return;
        }
        Integer overridenBCD = null;
        int bcdLocal = 0;
        BillingAlignment alignment = null;
        for (final SubscriptionBillingEvent transition : billingTransitions) {
            if (transition.getType() != SubscriptionBaseTransitionType.CANCEL) {
                final PlanPhaseSpecifier spec = new PlanPhaseSpecifier(transition.getPlan().getName(), transition.getPlanPhase().getPhaseType());
                alignment = subscription.getBillingAlignment(spec, transition.getEffectiveDate(), catalog);
                // 
                // A BCD_CHANGE transition defines a new billCycleDayLocal for the subscription and this overrides whatever computation
                // occurs below (which is based on billing alignment policy). Also multiple of those BCD_CHANGE transitions could occur,
                // to define different intervals with different billing cycle days.
                // 
                overridenBCD = transition.getBcdLocal() != null ? transition.getBcdLocal() : overridenBCD;
                bcdLocal = overridenBCD != null ? overridenBCD : calculateBcdForTransition(alignment, bcdCache, baseSubscription, subscription, currentAccountBCD, context);
            }
            final BillingEvent event = new DefaultBillingEvent(transition, subscription, bcdLocal, alignment, account.getCurrency());
            result.add(event);
        }
    }
}
Also used : SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) HashMap(java.util.HashMap) BillingAlignment(org.killbill.billing.catalog.api.BillingAlignment) SubscriptionBillingEvent(org.killbill.billing.subscription.api.user.SubscriptionBillingEvent) BillingEvent(org.killbill.billing.junction.BillingEvent) UUID(java.util.UUID) SubscriptionBillingEvent(org.killbill.billing.subscription.api.user.SubscriptionBillingEvent)

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