Search in sources :

Example 1 with SubscriptionBaseError

use of org.killbill.billing.subscription.exceptions.SubscriptionBaseError in project killbill by killbill.

the class DefaultSubscriptionInternalApi method verifyAndBuildSubscriptionSpecifiers.

private List<SubscriptionSpecifier> verifyAndBuildSubscriptionSpecifiers(final UUID bundleId, final String externalKey, final Iterable<EntitlementSpecifier> entitlements, final boolean isMigrated, final InternalCallContext context, final DateTime now, final DateTime effectiveDate, final Catalog catalog, final CallContext callContext) throws SubscriptionBaseApiException, CatalogApiException {
    final List<SubscriptionSpecifier> subscriptions = new ArrayList<SubscriptionSpecifier>();
    boolean first = true;
    final List<SubscriptionBase> subscriptionsForBundle = getSubscriptionsForBundle(bundleId, null, context);
    for (final EntitlementSpecifier entitlement : entitlements) {
        final PlanPhaseSpecifier spec = entitlement.getPlanPhaseSpecifier();
        final PlanPhasePriceOverridesWithCallContext overridesWithContext = new DefaultPlanPhasePriceOverridesWithCallContext(entitlement.getOverrides(), callContext);
        final Plan plan = catalog.createOrFindPlan(spec, overridesWithContext, effectiveDate);
        final PlanPhase phase = plan.getAllPhases()[0];
        if (phase == null) {
            throw new SubscriptionBaseError(String.format("No initial PlanPhase for Product %s, term %s and set %s does not exist in the catalog", spec.getProductName(), spec.getBillingPeriod().toString(), plan.getPriceListName()));
        }
        if (first) {
            first = false;
            if (plan.getProduct().getCategory() != ProductCategory.BASE) {
                throw new SubscriptionBaseApiException(new IllegalArgumentException(), ErrorCode.SUB_CREATE_NO_BP.getCode(), "Missing Base Subscription.");
            }
        }
        // verify the number of subscriptions (of the same kind) allowed per bundle and the existing ones
        if (ProductCategory.ADD_ON.toString().equalsIgnoreCase(plan.getProduct().getCategory().toString())) {
            if (plan.getPlansAllowedInBundle() != -1 && plan.getPlansAllowedInBundle() > 0) {
                final int existingAddOnsWithSamePlanName = addonUtils.countExistingAddOnsWithSamePlanName(subscriptionsForBundle, plan.getName());
                final int currentAddOnsWithSamePlanName = countCurrentAddOnsWithSamePlanName(entitlements, catalog, plan.getName(), effectiveDate, callContext);
                if ((existingAddOnsWithSamePlanName + currentAddOnsWithSamePlanName) > plan.getPlansAllowedInBundle()) {
                    // a new ADD_ON subscription of the same plan can't be added because it has reached its limit by bundle
                    throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_AO_MAX_PLAN_ALLOWED_BY_BUNDLE, plan.getName());
                }
            }
        }
        final SubscriptionSpecifier subscription = new SubscriptionSpecifier();
        subscription.setRealPriceList(plan.getPriceListName());
        subscription.setEffectiveDate(effectiveDate);
        subscription.setProcessedDate(now);
        subscription.setPlan(plan);
        subscription.setInitialPhase(spec.getPhaseType());
        subscription.setBuilder(new SubscriptionBuilder().setId(UUIDs.randomUUID()).setBundleId(bundleId).setBundleExternalKey(externalKey).setCategory(plan.getProduct().getCategory()).setBundleStartDate(effectiveDate).setAlignStartDate(effectiveDate).setMigrated(isMigrated));
        subscriptions.add(subscription);
    }
    return subscriptions;
}
Also used : SubscriptionSpecifier(org.killbill.billing.subscription.api.user.SubscriptionSpecifier) PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) ArrayList(java.util.ArrayList) SubscriptionBuilder(org.killbill.billing.subscription.api.user.SubscriptionBuilder) Plan(org.killbill.billing.catalog.api.Plan) SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) DefaultSubscriptionBase(org.killbill.billing.subscription.api.user.DefaultSubscriptionBase) EntitlementSpecifier(org.killbill.billing.entitlement.api.EntitlementSpecifier) PlanPhasePriceOverridesWithCallContext(org.killbill.billing.catalog.api.PlanPhasePriceOverridesWithCallContext) SubscriptionBaseError(org.killbill.billing.subscription.exceptions.SubscriptionBaseError) PlanPhase(org.killbill.billing.catalog.api.PlanPhase) SubscriptionBaseApiException(org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)

Example 2 with SubscriptionBaseError

use of org.killbill.billing.subscription.exceptions.SubscriptionBaseError in project killbill by killbill.

the class DefaultSubscriptionDao method uncancelSubscription.

@Override
public void uncancelSubscription(final DefaultSubscriptionBase subscription, final List<SubscriptionBaseEvent> uncancelEvents, final InternalCallContext context) {
    final InternalCallContext contextWithUpdatedDate = contextWithUpdatedDate(context);
    transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {

        @Override
        public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
            final SubscriptionEventSqlDao transactional = entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class);
            final UUID subscriptionId = subscription.getId();
            SubscriptionEventModelDao cancelledEvent = null;
            final Date now = clock.getUTCNow().toDate();
            final List<SubscriptionEventModelDao> eventModels = transactional.getFutureActiveEventForSubscription(subscriptionId.toString(), now, contextWithUpdatedDate);
            for (final SubscriptionEventModelDao cur : eventModels) {
                if (cur.getUserType() == ApiEventType.CANCEL) {
                    if (cancelledEvent != null) {
                        throw new SubscriptionBaseError(String.format("Found multiple cancelWithRequestedDate active events for subscriptions %s", subscriptionId.toString()));
                    }
                    cancelledEvent = cur;
                }
            }
            if (cancelledEvent != null) {
                final String cancelledEventId = cancelledEvent.getId().toString();
                transactional.unactiveEvent(cancelledEventId, contextWithUpdatedDate);
                for (final SubscriptionBaseEvent cur : uncancelEvents) {
                    transactional.create(new SubscriptionEventModelDao(cur), contextWithUpdatedDate);
                    recordFutureNotificationFromTransaction(entitySqlDaoWrapperFactory, cur.getEffectiveDate(), new SubscriptionNotificationKey(cur.getId()), contextWithUpdatedDate);
                }
                // Notify the Bus of the latest requested change
                notifyBusOfRequestedChange(entitySqlDaoWrapperFactory, subscription, uncancelEvents.get(uncancelEvents.size() - 1), SubscriptionBaseTransitionType.UNCANCEL, contextWithUpdatedDate);
            }
            return null;
        }
    });
}
Also used : InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) SubscriptionEventModelDao(org.killbill.billing.subscription.engine.dao.model.SubscriptionEventModelDao) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) SubscriptionApiException(org.killbill.billing.entitlement.api.SubscriptionApiException) IOException(java.io.IOException) EventBusException(org.killbill.bus.api.PersistentBus.EventBusException) EntityPersistenceException(org.killbill.billing.entity.EntityPersistenceException) Date(java.util.Date) SubscriptionNotificationKey(org.killbill.billing.subscription.engine.core.SubscriptionNotificationKey) SubscriptionBaseError(org.killbill.billing.subscription.exceptions.SubscriptionBaseError) EntitySqlDaoWrapperFactory(org.killbill.billing.util.entity.dao.EntitySqlDaoWrapperFactory) 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 3 with SubscriptionBaseError

use of org.killbill.billing.subscription.exceptions.SubscriptionBaseError in project killbill by killbill.

the class AddonUtils method isAddonIncludedFromPlanName.

public boolean isAddonIncludedFromPlanName(final String basePlanName, final Plan targetAddOnPlan, final DateTime requestedDate, final InternalTenantContext context) {
    try {
        final Plan plan = catalogService.getFullCatalog(true, true, context).findPlan(basePlanName, requestedDate);
        final Product product = plan.getProduct();
        return isAddonIncluded(product, targetAddOnPlan);
    } catch (CatalogApiException e) {
        throw new SubscriptionBaseError(e);
    }
}
Also used : SubscriptionBaseError(org.killbill.billing.subscription.exceptions.SubscriptionBaseError) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) Product(org.killbill.billing.catalog.api.Product) Plan(org.killbill.billing.catalog.api.Plan)

Example 4 with SubscriptionBaseError

use of org.killbill.billing.subscription.exceptions.SubscriptionBaseError in project killbill by killbill.

the class PlanAligner method getTimedPhaseOnCreate.

private List<TimedPhase> getTimedPhaseOnCreate(final DateTime subscriptionStartDate, final DateTime bundleStartDate, final Plan plan, @Nullable final PhaseType initialPhase, final SubscriptionCatalog catalog, final DateTime catalogEffectiveDate, final InternalTenantContext context) throws CatalogApiException, SubscriptionBaseApiException {
    final PlanSpecifier planSpecifier = new PlanSpecifier(plan.getName());
    final DateTime planStartDate;
    final PlanAlignmentCreate alignment = catalog.planCreateAlignment(planSpecifier, catalogEffectiveDate, subscriptionStartDate);
    switch(alignment) {
        case START_OF_SUBSCRIPTION:
            planStartDate = subscriptionStartDate;
            break;
        case START_OF_BUNDLE:
            planStartDate = bundleStartDate;
            break;
        default:
            throw new SubscriptionBaseError(String.format("Unknown PlanAlignmentCreate %s", alignment));
    }
    return getPhaseAlignments(plan, initialPhase, planStartDate);
}
Also used : SubscriptionBaseError(org.killbill.billing.subscription.exceptions.SubscriptionBaseError) PlanAlignmentCreate(org.killbill.billing.catalog.api.PlanAlignmentCreate) DateTime(org.joda.time.DateTime) PlanSpecifier(org.killbill.billing.catalog.api.PlanSpecifier)

Example 5 with SubscriptionBaseError

use of org.killbill.billing.subscription.exceptions.SubscriptionBaseError 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

SubscriptionBaseError (org.killbill.billing.subscription.exceptions.SubscriptionBaseError)22 DateTime (org.joda.time.DateTime)11 Plan (org.killbill.billing.catalog.api.Plan)7 PlanPhase (org.killbill.billing.catalog.api.PlanPhase)6 PlanPhaseSpecifier (org.killbill.billing.catalog.api.PlanPhaseSpecifier)6 ArrayList (java.util.ArrayList)5 DefaultSubscriptionBase (org.killbill.billing.subscription.api.user.DefaultSubscriptionBase)5 SubscriptionBaseEvent (org.killbill.billing.subscription.events.SubscriptionBaseEvent)5 CatalogApiException (org.killbill.billing.catalog.api.CatalogApiException)4 PlanSpecifier (org.killbill.billing.catalog.api.PlanSpecifier)4 SubscriptionBase (org.killbill.billing.subscription.api.SubscriptionBase)4 SubscriptionBaseApiException (org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)4 PhaseEvent (org.killbill.billing.subscription.events.phase.PhaseEvent)4 UUID (java.util.UUID)3 Catalog (org.killbill.billing.catalog.api.Catalog)3 SubscriptionBuilder (org.killbill.billing.subscription.api.user.SubscriptionBuilder)3 Date (java.util.Date)2 LinkedList (java.util.LinkedList)2 LocalDate (org.joda.time.LocalDate)2 InternalCallContext (org.killbill.billing.callcontext.InternalCallContext)2