Search in sources :

Example 1 with PlanPhase

use of org.killbill.billing.catalog.api.PlanPhase 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 PlanPhase

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

the class TestUserApiChangePlan method testChangePlanBundleAlignEOTWithChargeThroughDate.

private void testChangePlanBundleAlignEOTWithChargeThroughDate(final String fromProd, final BillingPeriod fromTerm, final String fromPlanSet, final String toProd, final BillingPeriod toTerm, final String toPlanSet) throws SubscriptionBillingApiException, SubscriptionBaseApiException {
    // CREATE
    DefaultSubscriptionBase subscription = testUtil.createSubscription(bundle, fromProd, fromTerm, fromPlanSet);
    final PlanPhase trialPhase = subscription.getCurrentPhase();
    final DateTime expectedPhaseTrialChange = TestSubscriptionHelper.addDuration(subscription.getStartDate(), trialPhase.getDuration());
    assertEquals(trialPhase.getPhaseType(), PhaseType.TRIAL);
    // MOVE TO NEXT PHASE
    testListener.pushExpectedEvent(NextEvent.PHASE);
    Interval it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusDays(31));
    clock.addDeltaFromReality(it.toDurationMillis());
    assertListenerStatus();
    PlanPhase currentPhase = subscription.getCurrentPhase();
    assertEquals(currentPhase.getPhaseType(), PhaseType.DISCOUNT);
    // SET CTD
    final Duration ctd = testUtil.getDurationMonth(1);
    final DateTime newChargedThroughDate = TestSubscriptionHelper.addDuration(expectedPhaseTrialChange, ctd);
    subscriptionInternalApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate, internalCallContext);
    // RE READ SUBSCRIPTION + CHANGE PLAN
    subscription = (DefaultSubscriptionBase) subscriptionInternalApi.getSubscriptionFromId(subscription.getId(), internalCallContext);
    subscription.changePlan(new PlanSpecifier(toProd, toTerm, toPlanSet), null, callContext);
    assertListenerStatus();
    // CHECK CHANGE PLAN
    currentPhase = subscription.getCurrentPhase();
    checkChangePlan(subscription, fromProd, ProductCategory.BASE, fromTerm, PhaseType.DISCOUNT);
    // NEXT PHASE
    final DateTime nextExpectedPhaseChange = TestSubscriptionHelper.addDuration(expectedPhaseTrialChange, currentPhase.getDuration());
    testUtil.checkNextPhaseChange(subscription, 2, nextExpectedPhaseChange);
    // ALSO VERIFY PENDING CHANGE EVENT
    final List<SubscriptionBaseEvent> events = dao.getPendingEventsForSubscription(subscription.getId(), internalCallContext);
    assertTrue(events.get(0) instanceof ApiEvent);
    // MOVE TO EOT
    testListener.pushExpectedEvent(NextEvent.CHANGE);
    it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusMonths(1));
    clock.addDeltaFromReality(it.toDurationMillis());
    assertListenerStatus();
    subscription = (DefaultSubscriptionBase) subscriptionInternalApi.getSubscriptionFromId(subscription.getId(), internalCallContext);
    currentPhase = subscription.getCurrentPhase();
    checkChangePlan(subscription, toProd, ProductCategory.BASE, toTerm, PhaseType.DISCOUNT);
    assertListenerStatus();
}
Also used : ApiEvent(org.killbill.billing.subscription.events.user.ApiEvent) PlanPhase(org.killbill.billing.catalog.api.PlanPhase) Duration(org.killbill.billing.catalog.api.Duration) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent) DateTime(org.joda.time.DateTime) Interval(org.joda.time.Interval) PlanSpecifier(org.killbill.billing.catalog.api.PlanSpecifier)

Example 3 with PlanPhase

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

the class TestUserApiChangePlan method tChangePlanChangePlanAlignEOTWithChargeThroughDate.

private void tChangePlanChangePlanAlignEOTWithChargeThroughDate(final String fromProd, final BillingPeriod fromTerm, final String fromPlanSet, final String toProd, final BillingPeriod toTerm, final String toPlanSet) throws SubscriptionBillingApiException, SubscriptionBaseApiException {
    DateTime currentTime = clock.getUTCNow();
    DefaultSubscriptionBase subscription = testUtil.createSubscription(bundle, fromProd, fromTerm, fromPlanSet);
    final PlanPhase trialPhase = subscription.getCurrentPhase();
    final DateTime expectedPhaseTrialChange = TestSubscriptionHelper.addDuration(subscription.getStartDate(), trialPhase.getDuration());
    assertEquals(trialPhase.getPhaseType(), PhaseType.TRIAL);
    // MOVE TO NEXT PHASE
    testListener.pushExpectedEvent(NextEvent.PHASE);
    currentTime = clock.getUTCNow();
    Interval it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusDays(31));
    clock.addDeltaFromReality(it.toDurationMillis());
    currentTime = clock.getUTCNow();
    assertListenerStatus();
    // SET CTD
    final Duration ctd = testUtil.getDurationMonth(1);
    final DateTime newChargedThroughDate = TestSubscriptionHelper.addDuration(expectedPhaseTrialChange, ctd);
    subscriptionInternalApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate, internalCallContext);
    // RE READ SUBSCRIPTION + CHECK CURRENT PHASE
    subscription = (DefaultSubscriptionBase) subscriptionInternalApi.getSubscriptionFromId(subscription.getId(), internalCallContext);
    PlanPhase currentPhase = subscription.getCurrentPhase();
    assertNotNull(currentPhase);
    assertEquals(currentPhase.getPhaseType(), PhaseType.EVERGREEN);
    // CHANGE PLAN
    currentTime = clock.getUTCNow();
    subscription.changePlan(new PlanSpecifier(toProd, toTerm, toPlanSet), null, callContext);
    checkChangePlan(subscription, fromProd, ProductCategory.BASE, fromTerm, PhaseType.EVERGREEN);
    // CHECK CHANGE DID NOT KICK IN YET
    assertListenerStatus();
    // MOVE TO AFTER CTD
    testListener.pushExpectedEvent(NextEvent.CHANGE);
    it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusMonths(1));
    clock.addDeltaFromReality(it.toDurationMillis());
    currentTime = clock.getUTCNow();
    assertListenerStatus();
    // CHECK CORRECT PRODUCT, PHASE, PLAN SET
    final String currentProduct = subscription.getCurrentPlan().getProduct().getName();
    assertNotNull(currentProduct);
    assertEquals(currentProduct, toProd);
    currentPhase = subscription.getCurrentPhase();
    assertNotNull(currentPhase);
    assertEquals(currentPhase.getPhaseType(), PhaseType.DISCOUNT);
    // MOVE TIME ABOUT ONE MONTH BEFORE NEXT EXPECTED PHASE CHANGE
    it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusMonths(11));
    clock.addDeltaFromReality(it.toDurationMillis());
    currentTime = clock.getUTCNow();
    assertListenerStatus();
    final DateTime nextExpectedPhaseChange = TestSubscriptionHelper.addDuration(newChargedThroughDate, currentPhase.getDuration());
    testUtil.checkNextPhaseChange(subscription, 1, nextExpectedPhaseChange);
    // MOVE TIME RIGHT AFTER NEXT EXPECTED PHASE CHANGE
    testListener.pushExpectedEvent(NextEvent.PHASE);
    it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusMonths(1));
    clock.addDeltaFromReality(it.toDurationMillis());
    currentTime = clock.getUTCNow();
    assertListenerStatus();
    assertListenerStatus();
}
Also used : PlanPhase(org.killbill.billing.catalog.api.PlanPhase) Duration(org.killbill.billing.catalog.api.Duration) DateTime(org.joda.time.DateTime) Interval(org.joda.time.Interval) PlanSpecifier(org.killbill.billing.catalog.api.PlanSpecifier)

Example 4 with PlanPhase

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

the class TestUserApiCreate method testSimpleCreateSubscription.

@Test(groups = "slow")
public void testSimpleCreateSubscription() throws SubscriptionBaseApiException {
    final DateTime init = clock.getUTCNow();
    final String productName = "Shotgun";
    final BillingPeriod term = BillingPeriod.MONTHLY;
    final String planSetName = PriceListSet.DEFAULT_PRICELIST_NAME;
    testListener.pushExpectedEvent(NextEvent.CREATE);
    final DefaultSubscriptionBase subscription = (DefaultSubscriptionBase) subscriptionInternalApi.createSubscription(bundle.getId(), testUtil.getProductSpecifier(productName, planSetName, term, null), null, clock.getUTCNow(), false, internalCallContext);
    assertNotNull(subscription);
    assertEquals(subscription.getBundleId(), bundle.getId());
    testUtil.assertDateWithin(subscription.getStartDate(), init, clock.getUTCNow());
    testUtil.assertDateWithin(subscription.getBundleStartDate(), init, clock.getUTCNow());
    final Plan currentPlan = subscription.getCurrentPlan();
    assertNotNull(currentPlan);
    assertEquals(currentPlan.getProduct().getName(), productName);
    assertEquals(currentPlan.getProduct().getCategory(), ProductCategory.BASE);
    assertEquals(currentPlan.getRecurringBillingPeriod(), BillingPeriod.MONTHLY);
    final PlanPhase currentPhase = subscription.getCurrentPhase();
    assertNotNull(currentPhase);
    assertEquals(currentPhase.getPhaseType(), PhaseType.TRIAL);
    assertListenerStatus();
    final List<SubscriptionBaseEvent> events = dao.getPendingEventsForSubscription(subscription.getId(), internalCallContext);
    assertNotNull(events);
    testUtil.printEvents(events);
    assertTrue(events.size() == 1);
    assertTrue(events.get(0) instanceof PhaseEvent);
    final DateTime nextPhaseChange = ((PhaseEvent) events.get(0)).getEffectiveDate();
    final DateTime nextExpectedPhaseChange = TestSubscriptionHelper.addDuration(subscription.getStartDate(), currentPhase.getDuration());
    assertEquals(nextPhaseChange, nextExpectedPhaseChange);
    testListener.pushExpectedEvent(NextEvent.PHASE);
    final Interval it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusDays(31));
    clock.addDeltaFromReality(it.toDurationMillis());
    final DateTime futureNow = clock.getUTCNow();
    assertTrue(futureNow.isAfter(nextPhaseChange));
    assertListenerStatus();
}
Also used : PhaseEvent(org.killbill.billing.subscription.events.phase.PhaseEvent) BillingPeriod(org.killbill.billing.catalog.api.BillingPeriod) PlanPhase(org.killbill.billing.catalog.api.PlanPhase) Plan(org.killbill.billing.catalog.api.Plan) SubscriptionBaseEvent(org.killbill.billing.subscription.events.SubscriptionBaseEvent) DateTime(org.joda.time.DateTime) Interval(org.joda.time.Interval) Test(org.testng.annotations.Test)

Example 5 with PlanPhase

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

the class TestUserApiCreate method testCreateWithInitialPhase.

@Test(groups = "slow")
public void testCreateWithInitialPhase() throws SubscriptionBaseApiException {
    final DateTime init = clock.getUTCNow();
    final String productName = "Shotgun";
    final BillingPeriod term = BillingPeriod.MONTHLY;
    final String planSetName = PriceListSet.DEFAULT_PRICELIST_NAME;
    testListener.pushExpectedEvent(NextEvent.CREATE);
    final DefaultSubscriptionBase subscription = (DefaultSubscriptionBase) subscriptionInternalApi.createSubscription(bundle.getId(), testUtil.getProductSpecifier(productName, planSetName, term, PhaseType.EVERGREEN), null, clock.getUTCNow(), false, internalCallContext);
    assertNotNull(subscription);
    assertEquals(subscription.getBundleId(), bundle.getId());
    testUtil.assertDateWithin(subscription.getStartDate(), init, clock.getUTCNow());
    testUtil.assertDateWithin(subscription.getBundleStartDate(), init, clock.getUTCNow());
    final Plan currentPlan = subscription.getCurrentPlan();
    assertNotNull(currentPlan);
    assertEquals(currentPlan.getProduct().getName(), productName);
    assertEquals(currentPlan.getProduct().getCategory(), ProductCategory.BASE);
    assertEquals(currentPlan.getRecurringBillingPeriod(), BillingPeriod.MONTHLY);
    final PlanPhase currentPhase = subscription.getCurrentPhase();
    assertNotNull(currentPhase);
    assertEquals(currentPhase.getPhaseType(), PhaseType.EVERGREEN);
    assertListenerStatus();
}
Also used : BillingPeriod(org.killbill.billing.catalog.api.BillingPeriod) PlanPhase(org.killbill.billing.catalog.api.PlanPhase) Plan(org.killbill.billing.catalog.api.Plan) DateTime(org.joda.time.DateTime) Test(org.testng.annotations.Test)

Aggregations

PlanPhase (org.killbill.billing.catalog.api.PlanPhase)98 Plan (org.killbill.billing.catalog.api.Plan)77 Test (org.testng.annotations.Test)71 MockPlan (org.killbill.billing.catalog.MockPlan)50 MockPlanPhase (org.killbill.billing.catalog.MockPlanPhase)49 LocalDate (org.joda.time.LocalDate)47 DateTime (org.joda.time.DateTime)43 BillingEventSet (org.killbill.billing.junction.BillingEventSet)43 BigDecimal (java.math.BigDecimal)42 BillingEvent (org.killbill.billing.junction.BillingEvent)41 MockBillingEventSet (org.killbill.billing.invoice.MockBillingEventSet)40 Invoice (org.killbill.billing.invoice.api.Invoice)39 DefaultInvoice (org.killbill.billing.invoice.model.DefaultInvoice)36 UUID (java.util.UUID)34 DefaultPrice (org.killbill.billing.catalog.DefaultPrice)22 MockInternationalPrice (org.killbill.billing.catalog.MockInternationalPrice)22 RecurringInvoiceItem (org.killbill.billing.invoice.model.RecurringInvoiceItem)22 SubscriptionBase (org.killbill.billing.subscription.api.SubscriptionBase)22 InvoiceItem (org.killbill.billing.invoice.api.InvoiceItem)21 FixedPriceInvoiceItem (org.killbill.billing.invoice.model.FixedPriceInvoiceItem)21