@Override public PlanPhaseSpecifier getPlanPhaseSpecifier() { return new PlanPhaseSpecifier(productName, term, planSet, phaseType); }
public PlanPhaseSpecifier getProductSpecifier(final String productName, final String priceList, final BillingPeriod term, @Nullable final PhaseType phaseType) { return new PlanPhaseSpecifier(productName, term, priceList, phaseType); }
protected void assertionNull(final DefaultCaseResult cr, final String productName, final ProductCategory productCategory, final BillingPeriod bp, final String priceListName, final PhaseType phaseType, final StandaloneCatalog cat) { try { Assert.assertNull(cr.getResult(new PlanPhaseSpecifier(productName, bp, priceListName, phaseType), cat)); } catch (CatalogApiException e) { Assert.fail("", e); } }
@Override public PlanPhaseSpecifier getPlanPhaseSpecifier() { return SubscriptionBaseTransitionType.CANCEL.equals(subscriptionTransitionType) ? null : new PlanPhaseSpecifier("1-BicycleTrialEvergreen1USD", BillingPeriod.NO_BILLING_PERIOD, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.FIXEDTERM); }
protected void assertion(final Result result, final DefaultCaseResult cr, final String productName, final ProductCategory productCategory, final BillingPeriod bp, final String priceListName, final PhaseType phaseType, final StandaloneCatalog cat) { try { Assert.assertEquals(result, cr.getResult(new PlanPhaseSpecifier(productName, bp, priceListName, phaseType), cat)); } catch (CatalogApiException e) { Assert.fail("", e); } } }
protected void assertion(final Result result, final DefaultCaseChangeResult cr, final String fromProductName, final String toProductName, final BillingPeriod fromBp, final BillingPeriod toBp, final String fromPriceListName, final String toPriceListName, final PhaseType phaseType, final StandaloneCatalog cat) { try { Assert.assertEquals(result, cr.getResult(new PlanPhaseSpecifier(fromProductName, fromBp, fromPriceListName, phaseType), new PlanSpecifier(toProductName, toBp, toPriceListName), cat)); } catch (CatalogApiException e) { Assert.fail("", e); } } }
protected void assertionNull(final DefaultCaseChangeResult cr, final String fromProductName, final String toProductName, final ProductCategory fromProductCategory, final ProductCategory toProductCategory, final BillingPeriod fromBp, final BillingPeriod toBp, final String fromPriceListName, final String toPriceListName, final PhaseType phaseType, final StandaloneCatalog cat) { try { Assert.assertNull(cr.getResult(new PlanPhaseSpecifier(fromProductName, fromBp, fromPriceListName, phaseType), new PlanSpecifier(toProductName, toBp, toPriceListName), cat)); } catch (CatalogApiException e) { Assert.fail("", e); } }
protected void assertionException(final DefaultCaseResult cr, final String productName, final ProductCategory productCategory, final BillingPeriod bp, final String priceListName, final PhaseType phaseType, final StandaloneCatalog cat) { try { Assert.assertNull(cr.getResult(new PlanPhaseSpecifier(productName, bp, priceListName, phaseType), cat)); Assert.fail("Exception expected"); } catch (CatalogApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.CAT_PRICE_LIST_NOT_FOUND.getCode()); } }
protected void assertionException(final DefaultCaseChangeResult cr, final String fromProductName, final String toProductName, final BillingPeriod fromBp, final BillingPeriod toBp, final String fromPriceListName, final String toPriceListName, final PhaseType phaseType, final StandaloneCatalog cat) { try { cr.getResult(new PlanPhaseSpecifier(fromProductName, fromBp, fromPriceListName, phaseType), new PlanSpecifier(toProductName, toBp, toPriceListName), cat); Assert.fail("Expecting an exception"); } catch (CatalogApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.CAT_PRICE_LIST_NOT_FOUND.getCode()); } }
private enum WhichPhase { CURRENT, NEXT }
@Override public boolean cancelWithPolicyNoValidationAndCatalog(final Iterable<DefaultSubscriptionBase> subscriptions, final BillingActionPolicy policy, final Catalog catalog, final InternalCallContext context) throws SubscriptionBaseApiException { final Map<DefaultSubscriptionBase, DateTime> subscriptionsWithEffectiveDate = new HashMap<DefaultSubscriptionBase, DateTime>(); try { for (final DefaultSubscriptionBase subscription : subscriptions) { final BillingAlignment billingAlignment = (subscription.getState() == EntitlementState.PENDING ? null : catalog.billingAlignment(new PlanPhaseSpecifier(subscription.getLastActivePlan().getName(), subscription.getLastActivePhase().getPhaseType()), clock.getUTCNow(), subscription.getStartDate())); final Integer accountBillCycleDayLocal = accountInternalApi.getBCD(context); final DateTime effectiveDate = subscription.getPlanChangeEffectiveDate(policy, billingAlignment, accountBillCycleDayLocal, context); subscriptionsWithEffectiveDate.put(subscription, effectiveDate); } return doCancelPlan(subscriptionsWithEffectiveDate, catalog, context); } catch (final CatalogApiException e) { throw new SubscriptionBaseApiException(e); } catch (final AccountApiException e) { throw new SubscriptionBaseApiException(e); } }
@Override public boolean cancel(final DefaultSubscriptionBase subscription, final CallContext context) throws SubscriptionBaseApiException { final EntitlementState currentState = subscription.getState(); if (currentState == EntitlementState.CANCELLED) { throw new SubscriptionBaseApiException(ErrorCode.SUB_CANCEL_BAD_STATE, subscription.getId(), currentState); } final Plan currentPlan = subscription.getCurrentOrPendingPlan(); final PlanPhaseSpecifier planPhase = new PlanPhaseSpecifier(currentPlan.getName(), null); try { final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context); final Catalog fullCatalog = catalogInternalApi.getFullCatalog(true, true, internalCallContext); final BillingActionPolicy policy = fullCatalog.planCancelPolicy(planPhase, clock.getUTCNow(), subscription.getStartDate()); Preconditions.checkState(policy != BillingActionPolicy.START_OF_TERM, "A default START_OF_TERM policy is not availaible"); final DateTime effectiveDate = subscription.getPlanChangeEffectiveDate(policy, null, -1, null); return doCancelPlan(ImmutableMap.<DefaultSubscriptionBase, DateTime>of(subscription, effectiveDate), fullCatalog, internalCallContext); } catch (final CatalogApiException e) { throw new SubscriptionBaseApiException(e); } }
@Test(groups = "slow") public void testChangePlanOnCreate() throws SubscriptionBaseApiException { final DefaultSubscriptionBase subscription = testUtil.createSubscription(bundle, "Shotgun", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME); // CHANGE PLAN IMMEDIATELY: the CHANGE event will be transformed into a CREATE testListener.pushExpectedEvent(NextEvent.CREATE); final PlanPhaseSpecifier planPhaseSpecifier = new PlanPhaseSpecifier("Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME); subscription.changePlanWithDate(new DefaultEntitlementSpecifier(planPhaseSpecifier), subscription.getStartDate(), callContext); assertListenerStatus(); checkChangePlan(subscription, "Pistol", ProductCategory.BASE, BillingPeriod.MONTHLY, PhaseType.TRIAL); final SubscriptionBase refreshedSubscription = subscriptionInternalApi.getSubscriptionFromId(subscription.getId(), internalCallContext); assertEquals(refreshedSubscription.getAllTransitions().size(), 2); assertEquals(refreshedSubscription.getAllTransitions().get(0).getTransitionType(), SubscriptionBaseTransitionType.CREATE); assertEquals(refreshedSubscription.getAllTransitions().get(1).getTransitionType(), SubscriptionBaseTransitionType.PHASE); }
@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); }
@Test(groups = "fast") public void testExistingPriceListIsKept() throws CatalogApiException { final DefaultProduct product1 = cat.getCurrentProduct(0); final DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME); final PlanPhaseSpecifier from = new PlanPhaseSpecifier(product1.getName(), BillingPeriod.MONTHLY, priceList1.getName(), PhaseType.EVERGREEN); final PlanSpecifier to = new PlanSpecifier(product1.getName(), BillingPeriod.ANNUAL, priceList1.getName()); PlanChangeResult result = null; try { result = cat.getPlanRules().planChange(from, to, cat); } catch (IllegalPlanChange e) { Assert.fail("We should not have triggered this error"); } catch (CatalogApiException e) { Assert.fail("", e); } Assert.assertEquals(result.getPolicy(), BillingActionPolicy.END_OF_TERM); Assert.assertEquals(result.getAlignment(), PlanAlignmentChange.START_OF_SUBSCRIPTION); Assert.assertEquals(result.getNewPriceList(), priceList1); }
@Test(groups = "slow") public void testChangePlanRightAfterCreate() throws SubscriptionBaseApiException { final DefaultSubscriptionBase subscription = testUtil.createSubscription(bundle, "Shotgun", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME); clock.setTime(clock.getUTCNow().plusSeconds(1)); // CHANGE PLAN ALMOST IMMEDIATELY testListener.pushExpectedEvent(NextEvent.CHANGE); final PlanPhaseSpecifier planPhaseSpecifier = new PlanPhaseSpecifier("Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME); subscription.changePlan(new DefaultEntitlementSpecifier(planPhaseSpecifier), callContext); assertListenerStatus(); checkChangePlan(subscription, "Pistol", ProductCategory.BASE, BillingPeriod.MONTHLY, PhaseType.TRIAL); final SubscriptionBase refreshedSubscription = subscriptionInternalApi.getSubscriptionFromId(subscription.getId(), internalCallContext); assertEquals(refreshedSubscription.getAllTransitions().size(), 3); assertEquals(refreshedSubscription.getAllTransitions().get(0).getTransitionType(), SubscriptionBaseTransitionType.CREATE); assertEquals(refreshedSubscription.getAllTransitions().get(1).getTransitionType(), SubscriptionBaseTransitionType.CHANGE); assertEquals(refreshedSubscription.getAllTransitions().get(2).getTransitionType(), SubscriptionBaseTransitionType.PHASE); }
@Override public PlanChangeResult getPlanChangeResult(final DefaultSubscriptionBase subscription, final PlanSpecifier toPlanPhase, final DateTime effectiveDate, final TenantContext context) throws SubscriptionBaseApiException { final PlanChangeResult planChangeResult; try { final InternalTenantContext internalCallContext = createTenantContextFromBundleId(subscription.getBundleId(), context); final Plan currentPlan = subscription.getCurrentOrPendingPlan(); final PlanPhaseSpecifier fromPlanPhase = new PlanPhaseSpecifier(currentPlan.getName(), subscription.getCurrentOrPendingPhase().getPhaseType()); planChangeResult = catalogInternalApi.getFullCatalog(true, true, internalCallContext).planChange(fromPlanPhase, toPlanPhase, effectiveDate, subscription.getStartDate()); } catch (final CatalogApiException e) { throw new SubscriptionBaseApiException(e); } return planChangeResult; }
@Test(groups = "fast") public void testChangeSubscriptionNonActive() throws SubscriptionBaseApiException { final SubscriptionBase subscription = testUtil.createSubscription(bundle, "Shotgun", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME); testListener.pushExpectedEvent(NextEvent.CANCEL); subscription.cancelWithDate(clock.getUTCNow(), callContext); assertListenerStatus(); try { final PlanPhaseSpecifier planPhaseSpecifier = new PlanPhaseSpecifier("Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME); subscription.changePlanWithDate(new DefaultEntitlementSpecifier(planPhaseSpecifier), clock.getUTCNow(), callContext); Assert.fail("Exception expected, error code: " + ErrorCode.SUB_CHANGE_NON_ACTIVE); } catch (final SubscriptionBaseApiException e) { assertEquals(e.getCode(), ErrorCode.SUB_CHANGE_NON_ACTIVE.getCode()); } }
@Test(groups = "fast") public void testBaseCase() throws CatalogApiException { final DefaultProduct product1 = cat.getCurrentProduct(0); final DefaultProduct product2 = cat.getCurrentProduct(1); final DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME); final DefaultPriceList priceList2 = cat.getPriceLists().getChildPriceLists()[0]; final PlanPhaseSpecifier from = new PlanPhaseSpecifier(product1.getName(), BillingPeriod.MONTHLY, priceList1.getName(), PhaseType.EVERGREEN); final PlanSpecifier to = new PlanSpecifier(product2.getName(), BillingPeriod.MONTHLY, null); PlanChangeResult result = null; try { result = cat.getPlanRules().planChange(from, to, cat); } catch (IllegalPlanChange e) { Assert.fail("We should not have triggered this error"); } catch (CatalogApiException e) { Assert.fail("", e); } Assert.assertEquals(result.getPolicy(), BillingActionPolicy.END_OF_TERM); Assert.assertEquals(result.getAlignment(), PlanAlignmentChange.START_OF_SUBSCRIPTION); Assert.assertEquals(result.getNewPriceList(), priceList2); } }
private void tChangePlanBundleAlignIMM(final String fromProd, final BillingPeriod fromTerm, final String fromPlanSet, final String toProd, final BillingPeriod toTerm, final String toPlanSet) throws SubscriptionBaseApiException { final DefaultSubscriptionBase subscription = testUtil.createSubscription(bundle, fromProd, fromTerm, fromPlanSet); testListener.pushExpectedEvent(NextEvent.CHANGE); Interval it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusDays(3)); clock.addDeltaFromReality(it.toDurationMillis()); // CHANGE PLAN IMM final PlanPhaseSpecifier planPhaseSpecifier = new PlanPhaseSpecifier(toProd, toTerm, toPlanSet); subscription.changePlan(new DefaultEntitlementSpecifier(planPhaseSpecifier), callContext); checkChangePlan(subscription, toProd, ProductCategory.BASE, toTerm, PhaseType.TRIAL); assertListenerStatus(); final PlanPhase currentPhase = subscription.getCurrentPhase(); final DateTime nextExpectedPhaseChange = TestSubscriptionHelper.addDuration(subscription.getStartDate(), currentPhase.getDuration()); testUtil.checkNextPhaseChange(subscription, 1, nextExpectedPhaseChange); // NEXT PHASE testListener.pushExpectedEvent(NextEvent.PHASE); it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusDays(30)); clock.addDeltaFromReality(it.toDurationMillis()); final DateTime futureNow = clock.getUTCNow(); assertTrue(futureNow.isAfter(nextExpectedPhaseChange)); assertListenerStatus(); }