Search in sources :

Example 1 with ProductCategory

use of org.killbill.billing.catalog.api.ProductCategory in project killbill by killbill.

the class DefaultSubscriptionBaseTimeline method toExistingEvents.

private List<ExistingEvent> toExistingEvents(final Catalog catalog, final ProductCategory category, final List<SubscriptionBaseEvent> events) throws CatalogApiException {
    final List<ExistingEvent> result = new LinkedList<SubscriptionBaseTimeline.ExistingEvent>();
    String prevPlanName = null;
    String prevProductName = null;
    BillingPeriod prevBillingPeriod = null;
    String prevPriceListName = null;
    PhaseType prevPhaseType = null;
    DateTime startDate = null;
    for (final SubscriptionBaseEvent cur : events) {
        if (!cur.isActive()) {
            continue;
        }
        startDate = (startDate == null) ? cur.getEffectiveDate() : startDate;
        String productName = null;
        BillingPeriod billingPeriod = null;
        String priceListName = null;
        PhaseType phaseType = null;
        String planName = null;
        String planPhaseName = null;
        Integer billCycleDayLocal = null;
        ApiEventType apiType = null;
        switch(cur.getType()) {
            case PHASE:
                final PhaseEvent phaseEV = (PhaseEvent) cur;
                planPhaseName = phaseEV.getPhase();
                phaseType = catalog.findPhase(phaseEV.getPhase(), cur.getEffectiveDate(), startDate).getPhaseType();
                // A PHASE event always occurs within the same plan (and is never the first event)
                planName = prevPlanName;
                productName = prevProductName;
                billingPeriod = getBillingPeriod(catalog, phaseEV.getPhase(), cur.getEffectiveDate(), startDate);
                priceListName = prevPriceListName;
                break;
            case BCD_UPDATE:
                final BCDEvent bcdEvent = (BCDEvent) cur;
                billCycleDayLocal = bcdEvent.getBillCycleDayLocal();
                break;
            case API_USER:
                final ApiEvent userEV = (ApiEvent) cur;
                apiType = userEV.getApiEventType();
                planName = userEV.getEventPlan();
                planPhaseName = userEV.getEventPlanPhase();
                final Plan plan = (userEV.getEventPlan() != null) ? catalog.findPlan(userEV.getEventPlan(), cur.getEffectiveDate(), startDate) : null;
                phaseType = (userEV.getEventPlanPhase() != null) ? catalog.findPhase(userEV.getEventPlanPhase(), cur.getEffectiveDate(), startDate).getPhaseType() : prevPhaseType;
                productName = (plan != null) ? plan.getProduct().getName() : prevProductName;
                billingPeriod = (userEV.getEventPlanPhase() != null) ? getBillingPeriod(catalog, userEV.getEventPlanPhase(), cur.getEffectiveDate(), startDate) : prevBillingPeriod;
                priceListName = (userEV.getPriceList() != null) ? userEV.getPriceList() : prevPriceListName;
                break;
        }
        final SubscriptionBaseTransitionType transitionType = SubscriptionBaseTransitionData.toSubscriptionTransitionType(cur.getType(), apiType);
        final String planNameWithClosure = planName;
        final String planPhaseNameWithClosure = planPhaseName;
        final Integer billCycleDayLocalWithClosure = billCycleDayLocal;
        final PlanPhaseSpecifier spec = new PlanPhaseSpecifier(planName, phaseType);
        result.add(new ExistingEvent() {

            @Override
            public SubscriptionBaseTransitionType getSubscriptionTransitionType() {
                return transitionType;
            }

            @Override
            public ProductCategory getProductCategory() {
                return category;
            }

            @Override
            public PlanPhaseSpecifier getPlanPhaseSpecifier() {
                return spec;
            }

            @Override
            public UUID getEventId() {
                return cur.getId();
            }

            @Override
            public DateTime getEffectiveDate() {
                return cur.getEffectiveDate();
            }

            @Override
            public String getPlanName() {
                return planNameWithClosure;
            }

            @Override
            public String getPlanPhaseName() {
                return planPhaseNameWithClosure;
            }

            @Override
            public Integer getBillCycleDayLocal() {
                return billCycleDayLocalWithClosure;
            }
        });
        prevPlanName = planName;
        prevProductName = productName;
        prevBillingPeriod = billingPeriod;
        prevPriceListName = priceListName;
        prevPhaseType = phaseType;
    }
    sortExistingEvent(result);
    return result;
}
Also used : ApiEventType(org.killbill.billing.subscription.events.user.ApiEventType) PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) PhaseEvent(org.killbill.billing.subscription.events.phase.PhaseEvent) BillingPeriod(org.killbill.billing.catalog.api.BillingPeriod) SubscriptionBaseTransitionType(org.killbill.billing.subscription.api.SubscriptionBaseTransitionType) BCDEvent(org.killbill.billing.subscription.events.bcd.BCDEvent) Plan(org.killbill.billing.catalog.api.Plan) LinkedList(java.util.LinkedList) DateTime(org.joda.time.DateTime) ApiEvent(org.killbill.billing.subscription.events.user.ApiEvent) PhaseType(org.killbill.billing.catalog.api.PhaseType) ProductCategory(org.killbill.billing.catalog.api.ProductCategory) UUID(java.util.UUID) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent)

Example 2 with ProductCategory

use of org.killbill.billing.catalog.api.ProductCategory in project killbill by killbill.

the class DefaultSubscriptionBaseTransferApi method transferBundle.

@Override
public SubscriptionBaseBundle transferBundle(final UUID sourceAccountId, final UUID destAccountId, final String bundleKey, final DateTime transferDate, final boolean transferAddOn, final boolean cancelImmediately, final CallContext context) throws SubscriptionBaseTransferApiException {
    final InternalCallContext fromInternalCallContext = internalCallContextFactory.createInternalCallContext(sourceAccountId, context);
    final InternalCallContext toInternalCallContext = internalCallContextFactory.createInternalCallContext(destAccountId, context);
    try {
        final SubscriptionCatalog catalog = subscriptionCatalogApi.getFullCatalog(fromInternalCallContext);
        final DateTime effectiveTransferDate = transferDate == null ? context.getCreatedDate() : transferDate;
        if (effectiveTransferDate.isAfter(context.getCreatedDate())) {
            // (subscription always expects the first event to be in the past)
            throw new SubscriptionBaseTransferApiException(ErrorCode.SUB_TRANSFER_INVALID_EFF_DATE, effectiveTransferDate);
        }
        final SubscriptionBaseBundle bundle = subscriptionBaseInternalApi.getActiveBundleForKey(catalog.getCatalog(), bundleKey, fromInternalCallContext);
        if (bundle == null) {
            throw new SubscriptionBaseTransferApiException(ErrorCode.SUB_CREATE_NO_BUNDLE, bundleKey);
        }
        // Get the bundle timeline for the old account
        final BundleBaseTimeline bundleBaseTimeline = timelineApi.getBundleTimeline(bundle, context);
        final DefaultSubscriptionBaseBundle subscriptionBundleData = new DefaultSubscriptionBaseBundle(bundleKey, destAccountId, effectiveTransferDate, bundle.getOriginalCreatedDate(), context.getCreatedDate(), context.getCreatedDate());
        final List<SubscriptionTransferData> subscriptionTransferDataList = new LinkedList<SubscriptionTransferData>();
        final List<TransferCancelData> transferCancelDataList = new LinkedList<TransferCancelData>();
        DateTime bundleStartdate = null;
        for (final SubscriptionBaseTimeline cur : bundleBaseTimeline.getSubscriptions()) {
            final DefaultSubscriptionBase oldSubscription = (DefaultSubscriptionBase) dao.getSubscriptionFromId(cur.getId(), catalog, fromInternalCallContext);
            // Skip already cancelled subscriptions
            if (oldSubscription.getState() == EntitlementState.CANCELLED) {
                continue;
            }
            final List<ExistingEvent> existingEvents = cur.getExistingEvents();
            final ProductCategory productCategory = existingEvents.get(0).getProductCategory();
            // on base plan cancellations, even though we don't support un-transfer today)
            if (productCategory != ProductCategory.ADD_ON || cancelImmediately) {
                // Create the cancelWithRequestedDate event on effectiveCancelDate
                final DateTime effectiveCancelDate = !cancelImmediately && oldSubscription.getChargedThroughDate() != null && effectiveTransferDate.isBefore(oldSubscription.getChargedThroughDate()) ? oldSubscription.getChargedThroughDate() : effectiveTransferDate;
                final SubscriptionBaseEvent cancelEvent = new ApiEventCancel(new ApiEventBuilder().setSubscriptionId(cur.getId()).setEffectiveDate(effectiveCancelDate).setFromDisk(true));
                final TransferCancelData cancelData = new TransferCancelData(oldSubscription, cancelEvent);
                transferCancelDataList.add(cancelData);
            }
            if (productCategory == ProductCategory.ADD_ON && !transferAddOn) {
                continue;
            }
            // We Align with the original subscription
            final DateTime subscriptionAlignStartDate = oldSubscription.getAlignStartDate();
            if (bundleStartdate == null) {
                bundleStartdate = oldSubscription.getStartDate();
            }
            // Create the new subscription for the new bundle on the new account
            final DefaultSubscriptionBase defaultSubscriptionBase = createSubscriptionForApiUse(new SubscriptionBuilder().setId(UUIDs.randomUUID()).setBundleId(subscriptionBundleData.getId()).setBundleExternalKey(subscriptionBundleData.getExternalKey()).setCategory(productCategory).setBundleStartDate(effectiveTransferDate).setAlignStartDate(subscriptionAlignStartDate), ImmutableList.<SubscriptionBaseEvent>of(), catalog, fromInternalCallContext);
            final List<SubscriptionBaseEvent> events = toEvents(existingEvents, defaultSubscriptionBase, effectiveTransferDate, fromInternalCallContext);
            final SubscriptionTransferData curData = new SubscriptionTransferData(defaultSubscriptionBase, events, null);
            subscriptionTransferDataList.add(curData);
        }
        final BundleTransferData bundleTransferData = new BundleTransferData(subscriptionBundleData, subscriptionTransferDataList);
        // Atomically cancelWithRequestedDate all subscription on old account and create new bundle, subscriptions, events for new account
        dao.transfer(sourceAccountId, destAccountId, bundleTransferData, transferCancelDataList, catalog, fromInternalCallContext, toInternalCallContext);
        return bundleTransferData.getData();
    } catch (SubscriptionBaseRepairException e) {
        throw new SubscriptionBaseTransferApiException(e);
    } catch (CatalogApiException e) {
        throw new SubscriptionBaseTransferApiException(e);
    }
}
Also used : InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) SubscriptionBaseTimeline(org.killbill.billing.subscription.api.timeline.SubscriptionBaseTimeline) SubscriptionCatalog(org.killbill.billing.subscription.catalog.SubscriptionCatalog) DateTime(org.joda.time.DateTime) ApiEventBuilder(org.killbill.billing.subscription.events.user.ApiEventBuilder) SubscriptionBaseBundle(org.killbill.billing.subscription.api.user.SubscriptionBaseBundle) DefaultSubscriptionBaseBundle(org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseBundle) DefaultSubscriptionBase(org.killbill.billing.subscription.api.user.DefaultSubscriptionBase) ExistingEvent(org.killbill.billing.subscription.api.timeline.SubscriptionBaseTimeline.ExistingEvent) BundleBaseTimeline(org.killbill.billing.subscription.api.timeline.BundleBaseTimeline) SubscriptionBaseRepairException(org.killbill.billing.subscription.api.timeline.SubscriptionBaseRepairException) DefaultSubscriptionBaseBundle(org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseBundle) ApiEventCancel(org.killbill.billing.subscription.events.user.ApiEventCancel) SubscriptionBuilder(org.killbill.billing.subscription.api.user.SubscriptionBuilder) LinkedList(java.util.LinkedList) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) ProductCategory(org.killbill.billing.catalog.api.ProductCategory) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent)

Example 3 with ProductCategory

use of org.killbill.billing.catalog.api.ProductCategory in project killbill by killbill.

the class DefaultCaseChange method getResult.

public T getResult(final PlanPhaseSpecifier from, final PlanSpecifier to, final StaticCatalog catalog) throws CatalogApiException {
    final Product inFromProduct;
    final BillingPeriod inFromBillingPeriod;
    final ProductCategory inFromProductCategory;
    final PriceList inFromPriceList;
    if (from.getPlanName() != null) {
        final Plan plan = catalog.findPlan(from.getPlanName());
        inFromProduct = plan.getProduct();
        inFromBillingPeriod = plan.getRecurringBillingPeriod();
        inFromProductCategory = plan.getProduct().getCategory();
        inFromPriceList = plan.getPriceList();
    } else {
        inFromProduct = catalog.findProduct(from.getProductName());
        inFromBillingPeriod = from.getBillingPeriod();
        inFromProductCategory = inFromProduct.getCategory();
        inFromPriceList = from.getPriceListName() != null ? catalog.findPriceList(from.getPriceListName()) : null;
    }
    final Product inToProduct;
    final BillingPeriod inToBillingPeriod;
    final ProductCategory inToProductCategory;
    final PriceList inToPriceList;
    if (to.getPlanName() != null) {
        final Plan plan = catalog.findPlan(to.getPlanName());
        inToProduct = plan.getProduct();
        inToBillingPeriod = plan.getRecurringBillingPeriod();
        inToProductCategory = plan.getProduct().getCategory();
        inToPriceList = plan.getPriceList();
    } else {
        inToProduct = catalog.findProduct(to.getProductName());
        inToBillingPeriod = to.getBillingPeriod();
        inToProductCategory = inToProduct.getCategory();
        inToPriceList = to.getPriceListName() != null ? catalog.findPriceList(to.getPriceListName()) : null;
    }
    if ((phaseType == null || from.getPhaseType() == phaseType) && (fromProduct == null || fromProduct.equals(inFromProduct)) && (fromProductCategory == null || fromProductCategory.equals(inFromProductCategory)) && (fromBillingPeriod == null || fromBillingPeriod.equals(inFromBillingPeriod)) && (this.toProduct == null || this.toProduct.equals(inToProduct)) && (this.toProductCategory == null || this.toProductCategory.equals(inToProductCategory)) && (this.toBillingPeriod == null || this.toBillingPeriod.equals(inToBillingPeriod)) && (fromPriceList == null || fromPriceList.equals(inFromPriceList)) && (toPriceList == null || toPriceList.equals(inToPriceList))) {
        return getResult();
    }
    return null;
}
Also used : BillingPeriod(org.killbill.billing.catalog.api.BillingPeriod) ProductCategory(org.killbill.billing.catalog.api.ProductCategory) DefaultProduct(org.killbill.billing.catalog.DefaultProduct) Product(org.killbill.billing.catalog.api.Product) Plan(org.killbill.billing.catalog.api.Plan) DefaultPriceList(org.killbill.billing.catalog.DefaultPriceList) PriceList(org.killbill.billing.catalog.api.PriceList)

Example 4 with ProductCategory

use of org.killbill.billing.catalog.api.ProductCategory in project killbill by killbill.

the class DefaultCase method satisfiesCase.

protected boolean satisfiesCase(final PlanSpecifier planPhase, final StaticCatalog c) throws CatalogApiException {
    final Product product;
    final BillingPeriod billingPeriod;
    final ProductCategory productCategory;
    final PriceList priceList;
    if (planPhase.getPlanName() != null) {
        final Plan plan = c.findPlan(planPhase.getPlanName());
        product = plan.getProduct();
        billingPeriod = plan.getRecurringBillingPeriod();
        productCategory = plan.getProduct().getCategory();
        priceList = plan.getPriceList();
    } else {
        product = c.findProduct(planPhase.getProductName());
        billingPeriod = planPhase.getBillingPeriod();
        productCategory = product.getCategory();
        priceList = getPriceList() != null ? c.findPriceList(planPhase.getPriceListName()) : null;
    }
    return (getProduct() == null || getProduct().equals(product)) && (getProductCategory() == null || getProductCategory().equals(productCategory)) && (getBillingPeriod() == null || getBillingPeriod().equals(billingPeriod)) && (getPriceList() == null || getPriceList().equals(priceList));
}
Also used : BillingPeriod(org.killbill.billing.catalog.api.BillingPeriod) ProductCategory(org.killbill.billing.catalog.api.ProductCategory) DefaultProduct(org.killbill.billing.catalog.DefaultProduct) Product(org.killbill.billing.catalog.api.Product) Plan(org.killbill.billing.catalog.api.Plan) PriceList(org.killbill.billing.catalog.api.PriceList) DefaultPriceList(org.killbill.billing.catalog.DefaultPriceList)

Example 5 with ProductCategory

use of org.killbill.billing.catalog.api.ProductCategory in project killbill by killbill.

the class DefaultSubscriptionBaseTimeline method toExistingEvents.

private List<ExistingEvent> toExistingEvents(final SubscriptionCatalog catalog, final ProductCategory category, final List<SubscriptionBaseEvent> events) throws CatalogApiException {
    final List<ExistingEvent> result = new LinkedList<SubscriptionBaseTimeline.ExistingEvent>();
    Plan prevPlan = null;
    String prevProductName = null;
    String prevPriceListName = null;
    PhaseType prevPhaseType = null;
    DateTime startDate = null;
    for (final SubscriptionBaseEvent cur : events) {
        if (!cur.isActive()) {
            continue;
        }
        startDate = (startDate == null) ? cur.getEffectiveDate() : startDate;
        String productName = null;
        String priceListName = null;
        PhaseType phaseType = null;
        Plan plan = null;
        String planPhaseName = null;
        Integer billCycleDayLocal = null;
        ApiEventType apiType = null;
        switch(cur.getType()) {
            case PHASE:
                final PhaseEvent phaseEV = (PhaseEvent) cur;
                planPhaseName = phaseEV.getPhase();
                // A PHASE event always occurs within the same plan (and is never the first event)
                phaseType = prevPlan != null ? prevPlan.findPhase(phaseEV.getPhase()).getPhaseType() : null;
                plan = prevPlan;
                productName = prevProductName;
                priceListName = prevPriceListName;
                break;
            case BCD_UPDATE:
                final BCDEvent bcdEvent = (BCDEvent) cur;
                billCycleDayLocal = bcdEvent.getBillCycleDayLocal();
                break;
            case API_USER:
                final ApiEvent userEV = (ApiEvent) cur;
                apiType = userEV.getApiEventType();
                planPhaseName = userEV.getEventPlanPhase();
                plan = (userEV.getEventPlan() != null) ? catalog.findPlan(userEV.getEventPlan(), cur.getEffectiveDate(), startDate) : null;
                phaseType = (plan != null && userEV.getEventPlanPhase() != null) ? plan.findPhase(userEV.getEventPlanPhase()).getPhaseType() : prevPhaseType;
                productName = (plan != null) ? plan.getProduct().getName() : prevProductName;
                priceListName = (userEV.getPriceList() != null) ? userEV.getPriceList() : prevPriceListName;
                break;
        }
        final SubscriptionBaseTransitionType transitionType = SubscriptionBaseTransitionData.toSubscriptionTransitionType(cur.getType(), apiType);
        final String planNameWithClosure = plan != null ? plan.getName() : null;
        final String planPhaseNameWithClosure = planPhaseName;
        final Integer billCycleDayLocalWithClosure = billCycleDayLocal;
        final PlanPhaseSpecifier spec = new PlanPhaseSpecifier(planNameWithClosure, phaseType);
        result.add(new ExistingEvent() {

            @Override
            public SubscriptionBaseTransitionType getSubscriptionTransitionType() {
                return transitionType;
            }

            @Override
            public ProductCategory getProductCategory() {
                return category;
            }

            @Override
            public PlanPhaseSpecifier getPlanPhaseSpecifier() {
                return spec;
            }

            @Override
            public UUID getEventId() {
                return cur.getId();
            }

            @Override
            public DateTime getEffectiveDate() {
                return cur.getEffectiveDate();
            }

            @Override
            public String getPlanName() {
                return planNameWithClosure;
            }

            @Override
            public String getPlanPhaseName() {
                return planPhaseNameWithClosure;
            }

            @Override
            public Integer getBillCycleDayLocal() {
                return billCycleDayLocalWithClosure;
            }
        });
        prevPlan = plan;
        prevProductName = productName;
        prevPriceListName = priceListName;
        prevPhaseType = phaseType;
    }
    sortExistingEvent(result);
    return result;
}
Also used : ApiEventType(org.killbill.billing.subscription.events.user.ApiEventType) PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) PhaseEvent(org.killbill.billing.subscription.events.phase.PhaseEvent) SubscriptionBaseTransitionType(org.killbill.billing.subscription.api.SubscriptionBaseTransitionType) BCDEvent(org.killbill.billing.subscription.events.bcd.BCDEvent) Plan(org.killbill.billing.catalog.api.Plan) LinkedList(java.util.LinkedList) DateTime(org.joda.time.DateTime) ApiEvent(org.killbill.billing.subscription.events.user.ApiEvent) PhaseType(org.killbill.billing.catalog.api.PhaseType) ProductCategory(org.killbill.billing.catalog.api.ProductCategory) UUID(java.util.UUID) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent)

Aggregations

ProductCategory (org.killbill.billing.catalog.api.ProductCategory)5 Plan (org.killbill.billing.catalog.api.Plan)4 LinkedList (java.util.LinkedList)3 DateTime (org.joda.time.DateTime)3 BillingPeriod (org.killbill.billing.catalog.api.BillingPeriod)3 SubscriptionBaseEvent (org.killbill.billing.subscription.events.SubscriptionBaseEvent)3 UUID (java.util.UUID)2 DefaultPriceList (org.killbill.billing.catalog.DefaultPriceList)2 DefaultProduct (org.killbill.billing.catalog.DefaultProduct)2 PhaseType (org.killbill.billing.catalog.api.PhaseType)2 PlanPhaseSpecifier (org.killbill.billing.catalog.api.PlanPhaseSpecifier)2 PriceList (org.killbill.billing.catalog.api.PriceList)2 Product (org.killbill.billing.catalog.api.Product)2 SubscriptionBaseTransitionType (org.killbill.billing.subscription.api.SubscriptionBaseTransitionType)2 BCDEvent (org.killbill.billing.subscription.events.bcd.BCDEvent)2 PhaseEvent (org.killbill.billing.subscription.events.phase.PhaseEvent)2 ApiEvent (org.killbill.billing.subscription.events.user.ApiEvent)2 ApiEventType (org.killbill.billing.subscription.events.user.ApiEventType)2 InternalCallContext (org.killbill.billing.callcontext.InternalCallContext)1 CatalogApiException (org.killbill.billing.catalog.api.CatalogApiException)1